From 63146cc863070e37659b65e4448f5dee9d299956 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 13:00:16 +0800 Subject: [PATCH 001/168] docs: capture shortlist-reform decisions on shortlist-reform branch Records the outcome of a grilling session with the maintainer that settled the redesign of awesome-python from a catalog into a curated shortlist of Obvious Choices per Use Case. Execution is held pending maintainer go-ahead, so these files let a fresh agent resume without re-litigating settled decisions: - CONTEXT.md: glossary of the editorial vocabulary (Use Case, Obvious Choice, Challenger, Displacement, Split, etc). - docs/adr/0001-shortlist-not-catalog.md: the ADR recording the decision, considered options, and consequences (status: proposed). - .gitignore: docs/ was wholesale-ignored; carve out docs/adr/ so the ADR can be tracked. Co-Authored-By: Claude --- .gitignore | 5 +-- CONTEXT.md | 45 ++++++++++++++++++++++++++ docs/adr/0001-shortlist-not-catalog.md | 26 +++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 CONTEXT.md create mode 100644 docs/adr/0001-shortlist-not-catalog.md diff --git a/.gitignore b/.gitignore index f081c83359..5fbd39f128 100644 --- a/.gitignore +++ b/.gitignore @@ -13,8 +13,9 @@ __pycache__/ website/output/ website/data/ -# docs -docs/ +# docs (except decision records) +docs/* +!docs/adr/ # agents .agents/ diff --git a/CONTEXT.md b/CONTEXT.md new file mode 100644 index 0000000000..5456ff32d0 --- /dev/null +++ b/CONTEXT.md @@ -0,0 +1,45 @@ +# Awesome Python Curation + +The editorial domain of awesome-python: which projects the list carries, how they are admitted, and how they are displaced. The list is a curated shortlist of obvious choices, not a catalog of everything good. + +## Language + +### List structure + +**Entry**: +A single listed project: `- [pypi-name](url) - Description.` The unit that is admitted, displaced, or pruned. + +**Section**: +A `###` heading in README.md (e.g. "Testing", "AI and Agents"). Sections group entries and live under a Thematic Group. +_Avoid_: Category (overloaded — the TOC calls them categories, but rules bind to Use Cases, not Sections) + +**Subcategory**: +A named bullet inside a Section with indented entries under it (e.g. "Mocking" inside "Testing"). Where present, each Subcategory is one Use Case. + +**Use Case**: +The unit of "it" in "one obvious way to do it": one distinct job a reader needs done. Defined by the list's existing structure — each Subcategory is a Use Case; a flat Section is a single Use Case. Submitters cannot define Use Cases; only the list structure does. +_Avoid_: Niche, micro-category + +### Admission + +**Serves Python Developers**: +The scope test for what belongs on the list at all: Python developers use it in their Python work. Implementation language is irrelevant — uv and ty are Rust and belong; a pure-Python library nobody uses in Python work does not. +_Avoid_: Python-first, written-in-Python (old requirement — removed) + +**Obvious Choice**: +An entry an experienced Python developer would name unprompted when asked "what do I use for [Use Case]?". Certified by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars. A standard-library module holds a slot only when it is itself the Obvious Choice for the Use Case, not merely relevant to it. +_Avoid_: Industry Standard (old lane name), awesome (unfalsifiable) + +**Cap**: +The per-Use-Case entry limit: up to 3 Obvious Choices plus up to 2 Challengers, hard maximum 5. A qualitative bar first, a numeric backstop second. + +**Displacement**: +The only admission path into a full Use Case: the PR names the entry it replaces and argues the newcomer does that entry's job better. One in, one out. +_Avoid_: One-in-one-out (informal alias) + +**Challenger**: +An entry (at most two per Use Case) that is not yet the Obvious Choice but is a credible successor to one. Its description must say so, and admission requires adoption-trajectory evidence, not popularity alone. +_Avoid_: Rising Star (old lane name), Hidden Gem (old lane name — concept removed entirely) + +**Split**: +Maintainer-only restructuring of an oversized Use Case into finer Use Cases (new Subcategories), chosen over trimming when the size reflects genuinely distinct jobs. A submitter's entry PR can never perform a Split. diff --git a/docs/adr/0001-shortlist-not-catalog.md b/docs/adr/0001-shortlist-not-catalog.md new file mode 100644 index 0000000000..68d51580e8 --- /dev/null +++ b/docs/adr/0001-shortlist-not-catalog.md @@ -0,0 +1,26 @@ +--- +status: proposed +--- + +# awesome-python is a shortlist of obvious choices, not a catalog + +By mid-2026 the list held 576 entries across 75 sections, with entry inflow up 24x year over year (96 additions in the trailing 12 months vs 4 the year before), concentrated in sections like AI and Agents (41 entries). The old acceptance model — three lanes (Industry Standard, Rising Star, Hidden Gem), only the first capped — admitted any project good enough in isolation, so categories grew without bound and stopped answering the reader's actual question: "what do I use for X?" We decided to reposition the list as a curated shortlist, per the Zen of Python: there should be one — and preferably only one — obvious way to do it. + +## The decision + +Each Use Case (a subcategory, or a flat section) lists at most its Obvious Choices — capped at 3 (provisional, to be reviewed after the prune), including at most one marked Challenger. Admission is by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars, and stated as final. Once a Use Case is at cap, the only way in is Displacement: the PR names the entry it replaces and argues the newcomer does that job better. Use Cases are defined by the list's existing structure; an entry PR can never create the subcategory it needs. Standard-library entries hold a slot only where the stdlib module is itself the obvious choice. The existing stock gets the same test retroactively: a staged, worst-first prune (per-section sweep commits), with removed entries deleted outright — git history is the archive. Resources sections (Newsletters, Podcasts, Websites) are out of scope for now. + +## Considered options + +- Keep the three-lane model with caps on every lane: rejected because the lanes answer the wrong question ("is this good enough to enter?") once admission is comparative; rising-star momentum becomes Displacement evidence rather than an admission ticket, and Hidden Gem is definitionally incompatible with "obvious". +- Rules-only, no retroactive prune: rejected because every rejection would face "but X is listed" precedent arguments, and readers would see no change. +- Archive removed entries in a separate file: rejected because it recreates the catalog one click away and dilutes the identity the change exists to restore. + +## Consequences + +- The steady-state list shrinks toward roughly 400 entries or fewer (Testing dry run: 23 → 14); most future PRs will be rejected for fullness, not badness. +- awesome-python.com loses long-tail search traffic for the hundreds of niche tool names it will no longer carry. Accepted deliberately: reader trust over search surface. +- Fast-moving domains (e.g. AI and Agents) list current leaders by usage and absorb churn through Displacement; an oversized Use Case is either trimmed or Split into finer Use Cases by the maintainer. +- Linked awesome-* lists (e.g. awesome-python-testing) remain as the escape valve for readers who want exhaustive catalogs. + +See CONTEXT.md for the vocabulary (Use Case, Obvious Choice, Challenger, Displacement, Split). From bd657b3a85661d4130109cd3d2582002c5f00719 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 13:04:22 +0800 Subject: [PATCH 002/168] docs: fix stale cap wording in shortlist ADR Cap changed to 3 obvious choices + up to 2 challengers (hard max 5) during review, but the ADR still described the old cap of 3 with at most one challenger. Co-Authored-By: Claude --- docs/adr/0001-shortlist-not-catalog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/adr/0001-shortlist-not-catalog.md b/docs/adr/0001-shortlist-not-catalog.md index 68d51580e8..6a300a22e5 100644 --- a/docs/adr/0001-shortlist-not-catalog.md +++ b/docs/adr/0001-shortlist-not-catalog.md @@ -8,7 +8,7 @@ By mid-2026 the list held 576 entries across 75 sections, with entry inflow up 2 ## The decision -Each Use Case (a subcategory, or a flat section) lists at most its Obvious Choices — capped at 3 (provisional, to be reviewed after the prune), including at most one marked Challenger. Admission is by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars, and stated as final. Once a Use Case is at cap, the only way in is Displacement: the PR names the entry it replaces and argues the newcomer does that job better. Use Cases are defined by the list's existing structure; an entry PR can never create the subcategory it needs. Standard-library entries hold a slot only where the stdlib module is itself the obvious choice. The existing stock gets the same test retroactively: a staged, worst-first prune (per-section sweep commits), with removed entries deleted outright — git history is the archive. Resources sections (Newsletters, Podcasts, Websites) are out of scope for now. +Each Use Case (a subcategory, or a flat section) lists at most its Obvious Choices — up to 3, plus up to 2 marked Challengers, hard maximum 5 (numbers provisional, to be reviewed after the prune). Admission is by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars, and stated as final. Once a Use Case is at cap, the only way in is Displacement: the PR names the entry it replaces and argues the newcomer does that job better. Use Cases are defined by the list's existing structure; an entry PR can never create the subcategory it needs. Standard-library entries hold a slot only where the stdlib module is itself the obvious choice. The existing stock gets the same test retroactively: a staged, worst-first prune (per-section sweep commits), with removed entries deleted outright — git history is the archive. Resources sections (Newsletters, Podcasts, Websites) are out of scope for now. ## Considered options From d4d518fc32304154bfc24d2430ea0a8f27db7f03 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 13:07:31 +0800 Subject: [PATCH 003/168] docs: fix stale claims in shortlist-not-catalog ADR ADR review found three stale claims: an unreviewed Testing dry-run cited as evidence for the projected list size, the Challenger path missing from the lane-rejection rationale, and no mention of judgment overriding known failure modes of the download-signal (CI/dependency-inflated counts, model weights vs. pip installs, large-but-specific audiences misread as niche). Co-Authored-By: Claude --- docs/adr/0001-shortlist-not-catalog.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/adr/0001-shortlist-not-catalog.md b/docs/adr/0001-shortlist-not-catalog.md index 6a300a22e5..20c577578c 100644 --- a/docs/adr/0001-shortlist-not-catalog.md +++ b/docs/adr/0001-shortlist-not-catalog.md @@ -8,17 +8,17 @@ By mid-2026 the list held 576 entries across 75 sections, with entry inflow up 2 ## The decision -Each Use Case (a subcategory, or a flat section) lists at most its Obvious Choices — up to 3, plus up to 2 marked Challengers, hard maximum 5 (numbers provisional, to be reviewed after the prune). Admission is by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars, and stated as final. Once a Use Case is at cap, the only way in is Displacement: the PR names the entry it replaces and argues the newcomer does that job better. Use Cases are defined by the list's existing structure; an entry PR can never create the subcategory it needs. Standard-library entries hold a slot only where the stdlib module is itself the obvious choice. The existing stock gets the same test retroactively: a staged, worst-first prune (per-section sweep commits), with removed entries deleted outright — git history is the archive. Resources sections (Newsletters, Podcasts, Websites) are out of scope for now. +Each Use Case (a subcategory, or a flat section) lists at most its Obvious Choices — up to 3, plus up to 2 marked Challengers, hard maximum 5 (numbers provisional, to be reviewed after the prune). Admission is by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars, and stated as final; judgment overrides the signal's known failure modes (CI/dependency-inflated counts, model releases consumed as weights rather than pip installs, large-but-specific audiences misread as "niche"). Once a Use Case is at cap, the only way in is Displacement: the PR names the entry it replaces and argues the newcomer does that job better. Use Cases are defined by the list's existing structure; an entry PR can never create the subcategory it needs. Standard-library entries hold a slot only where the stdlib module is itself the obvious choice. The existing stock gets the same test retroactively: a staged, worst-first prune (per-section sweep commits), with removed entries deleted outright — git history is the archive. Resources sections (Newsletters, Podcasts, Websites) are out of scope for now. ## Considered options -- Keep the three-lane model with caps on every lane: rejected because the lanes answer the wrong question ("is this good enough to enter?") once admission is comparative; rising-star momentum becomes Displacement evidence rather than an admission ticket, and Hidden Gem is definitionally incompatible with "obvious". +- Keep the three-lane model with caps on every lane: rejected because the lanes answer the wrong question ("is this good enough to enter?") once admission is comparative; rising-star momentum becomes evidence for a Challenger slot or a Displacement rather than an admission ticket of its own, and Hidden Gem is definitionally incompatible with "obvious". - Rules-only, no retroactive prune: rejected because every rejection would face "but X is listed" precedent arguments, and readers would see no change. - Archive removed entries in a separate file: rejected because it recreates the catalog one click away and dilutes the identity the change exists to restore. ## Consequences -- The steady-state list shrinks toward roughly 400 entries or fewer (Testing dry run: 23 → 14); most future PRs will be rejected for fullness, not badness. +- The list shrinks substantially: the maintainer-reviewed preview of the three largest sections kept 45 of 80 entries. Most future PRs will be rejected for fullness, not badness. - awesome-python.com loses long-tail search traffic for the hundreds of niche tool names it will no longer carry. Accepted deliberately: reader trust over search surface. - Fast-moving domains (e.g. AI and Agents) list current leaders by usage and absorb churn through Displacement; an oversized Use Case is either trimmed or Split into finer Use Cases by the maintainer. - Linked awesome-* lists (e.g. awesome-python-testing) remain as the escape valve for readers who want exhaustive catalogs. From 92180242004d928612e2fc0a07a39bf2e6f64e4c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 13:11:04 +0800 Subject: [PATCH 004/168] docs: fold serves-Python-developers scope test into ADR-0001 Per maintainer choice, the new scope test replaces the old primarily-written-in-Python (>50%) requirement: implementation language and packaging no longer matter as long as Python developers use the thing in their Python work (e.g. uv and ty are Rust; agent skill packs are markdown), while pure-Python projects nobody uses in Python work still don't qualify. Folded into the existing ADR rather than filed as a separate one. Co-Authored-By: Claude --- docs/adr/0001-shortlist-not-catalog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/adr/0001-shortlist-not-catalog.md b/docs/adr/0001-shortlist-not-catalog.md index 20c577578c..92812ce485 100644 --- a/docs/adr/0001-shortlist-not-catalog.md +++ b/docs/adr/0001-shortlist-not-catalog.md @@ -8,7 +8,7 @@ By mid-2026 the list held 576 entries across 75 sections, with entry inflow up 2 ## The decision -Each Use Case (a subcategory, or a flat section) lists at most its Obvious Choices — up to 3, plus up to 2 marked Challengers, hard maximum 5 (numbers provisional, to be reviewed after the prune). Admission is by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars, and stated as final; judgment overrides the signal's known failure modes (CI/dependency-inflated counts, model releases consumed as weights rather than pip installs, large-but-specific audiences misread as "niche"). Once a Use Case is at cap, the only way in is Displacement: the PR names the entry it replaces and argues the newcomer does that job better. Use Cases are defined by the list's existing structure; an entry PR can never create the subcategory it needs. Standard-library entries hold a slot only where the stdlib module is itself the obvious choice. The existing stock gets the same test retroactively: a staged, worst-first prune (per-section sweep commits), with removed entries deleted outright — git history is the archive. Resources sections (Newsletters, Podcasts, Websites) are out of scope for now. +The list's scope test is "serves Python developers", replacing the old "primarily written in Python (>50%)" requirement: implementation language and packaging are irrelevant when Python developers use the thing in their Python work (uv and ty are Rust; agent skill packs are markdown), while a pure-Python project nobody uses in Python work does not belong. Each Use Case (a subcategory, or a flat section) lists at most its Obvious Choices — up to 3, plus up to 2 marked Challengers, hard maximum 5 (numbers provisional, to be reviewed after the prune). Admission is by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars, and stated as final; judgment overrides the signal's known failure modes (CI/dependency-inflated counts, model releases consumed as weights rather than pip installs, large-but-specific audiences misread as "niche"). Once a Use Case is at cap, the only way in is Displacement: the PR names the entry it replaces and argues the newcomer does that job better. Use Cases are defined by the list's existing structure; an entry PR can never create the subcategory it needs. Standard-library entries hold a slot only where the stdlib module is itself the obvious choice. The existing stock gets the same test retroactively: a staged, worst-first prune (per-section sweep commits), with removed entries deleted outright — git history is the archive. Resources sections (Newsletters, Podcasts, Websites) are out of scope for now. ## Considered options From c413b8f1f6fec7eea3f7ecd11dadcf9a162cc691 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 13:12:28 +0800 Subject: [PATCH 005/168] docs: fix stale and inaccurate definitions in CONTEXT.md CONTEXT.md review found several definitions had drifted from the settled shortlist-reform decisions: - Entry: pypi-name placeholder contradicted the serves-Python-developers scope test, which explicitly treats implementation language and packaging as irrelevant; now named by PyPI package name when one exists, else repository name - Subcategory: example referenced a name that no longer matches the current README structure (Mock, not Mocking) - Thematic Group: referenced elsewhere in the doc but never defined; added - Use Case, Obvious Choice, Split: updated to match the settled cap/evidence/restructure decisions (maintainer-only structure changes, PyPI-download judgment with known failure modes noted, Split considered before trimming) Co-Authored-By: Claude --- CONTEXT.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index 5456ff32d0..b590fb9014 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -7,27 +7,30 @@ The editorial domain of awesome-python: which projects the list carries, how the ### List structure **Entry**: -A single listed project: `- [pypi-name](url) - Description.` The unit that is admitted, displaced, or pruned. +A single listed project: `- [name](url) - Description.` The unit that is admitted, displaced, or pruned. Named by PyPI package name when one exists, else by repository name. + +**Thematic Group**: +A bold group line (e.g. "AI & ML", "Web Development") that clusters Sections in the TOC and the Projects body. **Section**: A `###` heading in README.md (e.g. "Testing", "AI and Agents"). Sections group entries and live under a Thematic Group. _Avoid_: Category (overloaded — the TOC calls them categories, but rules bind to Use Cases, not Sections) **Subcategory**: -A named bullet inside a Section with indented entries under it (e.g. "Mocking" inside "Testing"). Where present, each Subcategory is one Use Case. +A named bullet inside a Section with indented entries under it (e.g. "Mock" inside "Testing"). Where present, each Subcategory is one Use Case. **Use Case**: -The unit of "it" in "one obvious way to do it": one distinct job a reader needs done. Defined by the list's existing structure — each Subcategory is a Use Case; a flat Section is a single Use Case. Submitters cannot define Use Cases; only the list structure does. +The unit of "it" in "one obvious way to do it": one distinct job a reader needs done. Defined by the list's structure — each Subcategory is a Use Case; a flat Section is a single Use Case. Submitters cannot define Use Cases; only the maintainer changes the structure (see Split). _Avoid_: Niche, micro-category ### Admission **Serves Python Developers**: -The scope test for what belongs on the list at all: Python developers use it in their Python work. Implementation language is irrelevant — uv and ty are Rust and belong; a pure-Python library nobody uses in Python work does not. +The scope test for what belongs on the list at all: Python developers use it in their Python work. Implementation language and packaging are irrelevant — uv and ty are Rust and belong; a pure-Python library nobody uses in Python work does not. _Avoid_: Python-first, written-in-Python (old requirement — removed) **Obvious Choice**: -An entry an experienced Python developer would name unprompted when asked "what do I use for [Use Case]?". Certified by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars. A standard-library module holds a slot only when it is itself the Obvious Choice for the Use Case, not merely relevant to it. +An entry an experienced Python developer would name unprompted when asked "what do I use for [Use Case]?". Certified by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars; judgment overrides the signal's known failure modes (CI-inflated counts, model releases consumed as weights rather than pip installs, large-but-specific audiences misread as "niche"). A standard-library module holds a slot only when it is itself the Obvious Choice for the Use Case, not merely relevant to it. _Avoid_: Industry Standard (old lane name), awesome (unfalsifiable) **Cap**: @@ -42,4 +45,4 @@ An entry (at most two per Use Case) that is not yet the Obvious Choice but is a _Avoid_: Rising Star (old lane name), Hidden Gem (old lane name — concept removed entirely) **Split**: -Maintainer-only restructuring of an oversized Use Case into finer Use Cases (new Subcategories), chosen over trimming when the size reflects genuinely distinct jobs. A submitter's entry PR can never perform a Split. +Maintainer-only restructuring of an oversized Use Case into finer Use Cases (new Subcategories), considered before any trimming when the size reflects genuinely distinct jobs. A submitter's entry PR can never perform a Split. From 663fad0bafcf5543d585086a41e2dd7d6c987ad2 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 13:43:21 +0800 Subject: [PATCH 006/168] docs: mark Challengers by ordering, not description text A 2026-08-15 grilling round replaced the Challenger marking convention: within a Use Case, Obvious Choices are listed first (alphabetically), then Challengers (alphabetically), with no marker in the entry text. Update the Challenger definition in CONTEXT.md. Co-Authored-By: Claude --- CONTEXT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTEXT.md b/CONTEXT.md index b590fb9014..d89804b31a 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -41,7 +41,7 @@ The only admission path into a full Use Case: the PR names the entry it replaces _Avoid_: One-in-one-out (informal alias) **Challenger**: -An entry (at most two per Use Case) that is not yet the Obvious Choice but is a credible successor to one. Its description must say so, and admission requires adoption-trajectory evidence, not popularity alone. +An entry (at most two per Use Case) that is not yet the Obvious Choice but is a credible successor to one. Marked by ordering, not description: within a Use Case, Obvious Choices are listed first (alphabetically), then Challengers (alphabetically). Admission requires adoption-trajectory evidence, not popularity alone. _Avoid_: Rising Star (old lane name), Hidden Gem (old lane name — concept removed entirely) **Split**: From 553bf88c0598031c525a39cbc6d05d7d653566c6 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 13:51:18 +0800 Subject: [PATCH 007/168] feat: replace acceptance lanes with shortlist admission rule Land the shortlist-reform rules approved by the maintainer (rules first; entry sweeps are not authorized yet). - CONTRIBUTING.md: replace the Industry Standard / Rising Star / Hidden Gem lanes with a single admission rule per use case (up to 3 obvious choices + up to 2 challengers, hard max 5), add Displacement, the stdlib rule, and editorial-judgment-as-final evidence guidance; scope test becomes Serves Python Developers; document entry ordering (obvious choices then challengers, each alphabetical). - README.md: add the shortlist promise paragraph pointing rejected contributors to linked awesome-* catalogs and to CONTRIBUTING.md. - CLAUDE.md: sync Key Rules with the new ordering and shortlist cap, and add the prune-sweep one-commit-per-section exception. - docs/adr/0001-shortlist-not-catalog.md: flip status from proposed to accepted. Co-Authored-By: Claude --- CLAUDE.md | 10 ++--- CONTRIBUTING.md | 58 +++++++++++++------------- README.md | 2 + docs/adr/0001-shortlist-not-catalog.md | 2 +- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a6a15c1665..402cf791ff 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,11 +6,11 @@ An opinionated list of Python frameworks, libraries, tools, and resources. Publi ## Entry Guidelines -**Refer to [CONTRIBUTING.md](CONTRIBUTING.md)** for acceptance criteria, quality requirements, rejection rules, and entry format. Apply these rules whenever adding or removing an entry, whether reviewing a PR or committing directly. +**Refer to [CONTRIBUTING.md](CONTRIBUTING.md)** for admission rules, quality requirements, rejection rules, and entry format. Apply these rules whenever adding or removing an entry, whether reviewing a PR or committing directly. ## Structure -- **README.md**: Source of truth. Hierarchical categories with alphabetically ordered entries. +- **README.md**: Source of truth. Hierarchical categories; entries ordered per the Key Rules below. - **CONTRIBUTING.md**: Submission guidelines and review criteria. - **SPONSORSHIP.md**: Sponsor tiers, placement rules, and the editorial-independence policy. Sponsor content sits in the README header and must never influence which projects get listed. - **website/**: Static site generator that builds awesome-python.com from README.md. @@ -24,8 +24,8 @@ An opinionated list of Python frameworks, libraries, tools, and resources. Publi ## Key Rules -- Alphabetical ordering within categories is mandatory. -- Quality over quantity. Only "awesome" projects. +- Ordering within a use case: obvious choices first (alphabetically), then challengers (alphabetically). See CONTRIBUTING.md. +- A shortlist, not a catalog: per use case, up to 3 obvious choices plus up to 2 challengers, hard maximum 5. - One project per PR. -- One entry per commit when adding or deleting entries. Format, wording, or categorization changes across multiple entries may be bundled in a single commit. +- One entry per commit when adding or deleting entries. Exception: a prune sweep is one commit per section, its body listing each removal with its reason. Format, wording, or categorization changes across multiple entries may be bundled in a single commit. - README.md is the single source of content truth. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c3dd6c78f2..2367c766a5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,41 +1,35 @@ # Contributing +awesome-python is a shortlist, not a catalog. Each use case lists only its obvious choices, and most rejections mean "the use case is full", not "your project is bad". Read this whole page before opening a PR. + ## Quality Requirements All submissions must satisfy **ALL** of these: -1. **Python-first**: Primarily written in Python (>50% of codebase) +1. **Serves Python Developers**: Python developers use it in their Python work. Implementation language and packaging are irrelevant — uv and ty are written in Rust, and agent skill packs are markdown, yet all belong; a pure-Python project nobody uses in Python work does not. 2. **Active**: Commits within the last 12 months 3. **Stable**: Production-ready, not alpha/beta/experimental 4. **Documented**: Clear README with examples and use cases -5. **Unique**: Adds distinct value, not "yet another X" -6. **Established**: Repository at least 1 month old +5. **Established**: Repository at least 1 month old + +## Admission -## Acceptance Criteria +A **use case** is one distinct job a reader needs done. Use cases are defined by the list's structure: each subcategory is a use case, and a section without subcategories is a single use case. Structure changes — new sections, new subcategories, splitting an oversized use case into finer ones — are made only by the maintainer; an entry PR can never create the subcategory it needs. -Your submission must meet **ONE** of the following criteria: +Each use case lists at most: -### 1. Industry Standard +- **Up to 3 obvious choices** — tools an experienced Python developer would name unprompted when asked "what do I use for this?" +- **Up to 2 challengers** — tools that are not yet the obvious choice but are credible successors to one. Admission as a challenger requires adoption-trajectory evidence, not popularity alone. -- The go-to tool that almost everyone uses for a specific use case -- Examples: requests, flask, pandas, numpy -- Limit: 1-3 tools per category +Hard maximum: 5 entries per use case. This is a qualitative bar first and a numeric backstop second — most use cases should carry fewer. -### 2. Rising Star +**Displacement**: once a use case is at its cap, the only way in is to name the entry your project replaces and argue that yours does that entry's job better. One in, one out. -- Rapid growth: 5,000+ GitHub stars in less than 1 year -- Significant community buzz and adoption -- Solving problems in new or better ways -- Examples: fastapi, ruff, uv +**Standard library**: a standard-library module is listed only where the stdlib is itself the obvious choice for the use case (tomllib yes, unittest no). -### 3. Hidden Gem +**Evidence**: admission is decided by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars. Judgment overrides the signal's known failure modes (CI-inflated counts, model releases consumed as weights rather than pip installs, large-but-specific audiences misread as "niche"). The maintainer's decision is final. -- Exceptional quality despite fewer stars (100-500 stars preferred; < 100 requires strong justification) -- Solves niche problems elegantly -- Strong recommendation from experienced developers -- **Must demonstrate real-world usage** (not a project published last week) -- Repository must be at least 3 months old with consistent activity -- Must include compelling justification in PR description +Looking for an exhaustive catalog instead? Follow the awesome-* lists linked under individual entries (for example awesome-python-testing) — they exist precisely so this list doesn't have to be one. ## Entry Format Reference @@ -77,22 +71,28 @@ Use the **PyPI package name** as the display name so developers can copy it dire - [project](url) - Description. ``` -## Adding a New Section +### Entry Ordering + +Within a use case, the obvious choices are listed first, alphabetically; challengers follow, alphabetically. There is no marker in the entry text — position is the marker, so the last entries of a use case may be its challengers. + +## Changing the Structure + +Adding sections or subcategories is maintainer-only (see Admission). For maintainer reference: -1. Add section description in italics: `*Libraries for doing X.*` +1. Add the section description in italics: `*Libraries for doing X.*` 2. Add the section under the appropriate thematic group (e.g., **AI & ML**, **Web**, **Data & Science**) 3. Add the section title to the Table of Contents under its group -4. Keep entries in alphabetical order within each category +4. Order entries per Entry Ordering above ## Review Process PRs are reviewed by automated tools and maintainers: 1. **Format Check**: Entry follows the correct format -2. **Category Check**: Placed in the appropriate category/subcategory +2. **Category Check**: Placed in the appropriate use case 3. **Duplicate Check**: Not already listed or previously rejected 4. **Activity Check**: Project shows recent activity -5. **Quality Check**: Meets acceptance criteria +5. **Admission Check**: Meets the Admission rules above, including Displacement when the use case is at its cap Search previous Pull Requests and Issues before submitting, as yours may be a duplicate. @@ -101,10 +101,12 @@ Search previous Pull Requests and Issues before submitting, as yours may be a du PRs will be **closed** if: - Adding multiple projects in one PR +- The use case is at its cap and the PR makes no Displacement argument +- The PR creates a new section or subcategory and fills it (structure changes are maintainer-only) +- Coordinated multi-entry self-promotion: multiple related projects from the same organization or author, across one or several PRs - Duplicate of existing entry or recently-closed PR - Empty or placeholder PR descriptions - Placed under an inappropriate category - Project is archived or abandoned (no commits in 12+ months) - No documentation or unclear use case -- Less than 100 GitHub stars without Hidden Gem justification -- Repository less than 1 months old +- Repository less than 1 month old diff --git a/README.md b/README.md index 19662a181f..97fc877efe 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ An opinionated guide to the best Python frameworks, libraries, tools, and resources. +Every category is a shortlist, not a catalog: at most a few obvious choices per use case, kept short by editorial judgment informed by real-world usage. A missing project usually means its category is full — [CONTRIBUTING.md](CONTRIBUTING.md) explains how entries get in and what it takes to displace one. For exhaustive catalogs, follow the linked awesome-* lists. + **Visit the [website](https://awesome-python.com/) to search and filter projects more easily.** ## **Sponsors** diff --git a/docs/adr/0001-shortlist-not-catalog.md b/docs/adr/0001-shortlist-not-catalog.md index 92812ce485..095fad3866 100644 --- a/docs/adr/0001-shortlist-not-catalog.md +++ b/docs/adr/0001-shortlist-not-catalog.md @@ -1,5 +1,5 @@ --- -status: proposed +status: accepted --- # awesome-python is a shortlist of obvious choices, not a catalog From 3ca241dc4684153e95fca61930bf8fd6c94d47f9 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 14:15:18 +0800 Subject: [PATCH 008/168] clean up --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 97fc877efe..a0480ae8a0 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ An opinionated guide to the best Python frameworks, libraries, tools, and resources. -Every category is a shortlist, not a catalog: at most a few obvious choices per use case, kept short by editorial judgment informed by real-world usage. A missing project usually means its category is full — [CONTRIBUTING.md](CONTRIBUTING.md) explains how entries get in and what it takes to displace one. For exhaustive catalogs, follow the linked awesome-* lists. - **Visit the [website](https://awesome-python.com/) to search and filter projects more easily.** ## **Sponsors** @@ -550,6 +548,7 @@ _Libraries for visualizing data. Also see [awesome-javascript](https://github.co - Dashboards and Apps - [gradio](https://github.com/gradio-app/gradio) - Build and share machine learning apps, all in Python. - [streamlit](https://github.com/streamlit/streamlit) - A framework which lets you build dashboards, generate reports, or create chat apps in minutes. + ### Geolocation _Libraries for geocoding addresses and working with latitudes and longitudes._ @@ -872,7 +871,7 @@ _Libraries for working with graphical user interface applications._ - [toga](https://github.com/beeware/toga) - A Python native, OS native GUI toolkit. - [wxPython](https://github.com/wxWidgets/Phoenix) - A blending of the wxWidgets C++ class library with the Python. - Web-based - - [buridan/ui](https://github.com/LineIndent/ui) - Composable, themeable components designed for Reflex. Extend, override, and ship without fighting the framework. Open source. + - [buridan/ui](https://github.com/LineIndent/ui) - Composable, themeable components designed for Reflex. Extend, override, and ship without fighting the framework. Open source. - [flet](https://github.com/flet-dev/flet) - Cross-platform GUI framework for building modern apps in pure Python. - [nicegui](https://github.com/zauberzeug/nicegui) - An easy-to-use, Python-based UI framework, which shows up in your web browser. - [pywebview](https://github.com/r0x0r/pywebview/) - A lightweight cross-platform native wrapper around a webview component. From e10ff581568ac75466ae679cfbb307cb433c92d3 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 14:36:39 +0800 Subject: [PATCH 009/168] prune: sweep AI and Agents to the shortlist cap Per ADR-0001, restructure first: split Pre-trained Models and Inference into Pre-trained Models, LLM Inference and Serving, and LLM Gateways; mint Vendor Agent SDKs, Personal Assistants, Prompt Optimization, Image and Video Generation, and Fine-tuning subcategories. Re-home openai-agents (Vendor Agent SDKs), hermes-agent (Personal Assistants, description reworded to personal assistant), dspy (Prompt Optimization), diffusers (Image and Video Generation), unsloth (Fine-tuning), and graphify (Data Visualization > Specialized). Then cap. Removed (downloads are PyPI last-month via pypistats, 2026-08-14/15): - nuwa-skill: persona prompts, not engineering - crewai (19.4M/month): buzz peaked; no longer named unprompted - autogen (1.1M/month): fork war with ag2 split its community - ag2 (441K/month): other half of the same fork war - smolagents (651K/month): Hugging Face ecosystem niche - TradingAgents (11.9K/month): vertical trading app, not general orchestration - bub (5.6K/month): no adoption - bindu (210/month): no adoption - livetalking: no PyPI presence, no adoption evidence - bernstein: no PyPI presence, no adoption evidence - promptise: no PyPI presence, no adoption evidence - OpenChronicle: no PyPI presence, no adoption evidence - outlines (2.5M/month): same job as instructor, which holds the slot - entroly (3.1K/month): no adoption - lumen (1.8K/month): no adoption - liter-llm (3.5K/month): xberg-io coordinated self-promotion plant - SenseVoice: whisper wins the use case - voxcpm (101K/month): no track record Co-Authored-By: Claude --- README.md | 43 ++++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index a0480ae8a0..f87a4ef6c3 100644 --- a/README.md +++ b/README.md @@ -134,50 +134,38 @@ _Libraries for building AI applications, LLM integrations, and autonomous agents - Agent Skills - [django-ai-plugins](https://github.com/vintasoftware/django-ai-plugins) - Django backend agent skills for Django, DRF, Celery, and Django-specific code review. - - [graphify](https://github.com/safishamsi/graphify) - Turn any folder of code, SQL schemas, docs, papers, images, or videos into a queryable knowledge graph. - - [nuwa-skill](https://github.com/alchaincyf/nuwa-skill/blob/main/README_EN.md) - Nuwa distills the thinking of anyone — let Musk, Naval, Munger, and Feynman work for you. - [sentry-skills](https://github.com/getsentry/skills) - Python-focused engineering skills for code review, debugging, and backend workflows. - [trailofbits-skills](https://github.com/trailofbits/skills) - Python-friendly security skills for auditing, testing, and safer backend development. - Orchestration - - [ag2](https://github.com/ag2ai/ag2) - An open-source AgentOS for multi-agent orchestration and building agentic AI systems. - - [autogen](https://github.com/microsoft/autogen) - A programming framework for building agentic AI applications. - - [bernstein](https://github.com/sipyourdrink-ltd/bernstein) - A deterministic Python orchestrator for CLI coding agents (Claude Code, Codex, Gemini CLI, and 40+ more) with parallel git worktrees and an HMAC-signed audit chain. - - [bindu](https://github.com/getbindu/Bindu) - A framework that wraps any agent handler with DID-based cryptographic identity, A2A JSON-RPC over HTTP, OAuth2 auth, x402 (USDC) payments, and a built-in operator inbox. - - [bub](https://github.com/bubbuild/bub) - A lightweight, hook-first Python framework for channel-native agents that live alongside people. - - [crewai](https://github.com/crewAIInc/crewAI) - A framework for orchestrating role-playing autonomous AI agents for collaborative task solving. - - [dspy](https://github.com/stanfordnlp/dspy) - A framework for programming, not prompting, language models. - - [hermes-agent](https://github.com/nousresearch/hermes-agent) - An adaptive AI agent framework that grows with you. - [langchain](https://github.com/langchain-ai/langchain) - Building applications with LLMs through composability. - [langgraph](https://github.com/langchain-ai/langgraph) - Low-level orchestration framework for building stateful, long-running LLM agents. - - [livetalking](https://github.com/lipku/livetalking) - A framework for real time interactive streaming digital human. - - [openai-agents](https://github.com/openai/openai-agents-python) - OpenAI's framework for building and managing AI agents. - - [OpenChronicle](https://github.com/Einsia/OpenChronicle) - Open-source, local-first memory for any tool-capable LLM agent. - - [promptise](https://github.com/promptise-com/foundry) - A framework for building end-to-end production-ready agentic systems, scalable & secure MCP's and autonomous agents. - [pydantic-ai](https://github.com/pydantic/pydantic-ai) - A Python agent framework for building generative AI applications with structured schemas. - - [smolagents](https://github.com/huggingface/smolagents) - A lightweight library to build agents and multi-agent workflows with minimal code. - - [TradingAgents](https://github.com/TauricResearch/TradingAgents) - A multi-agents LLM financial trading framework. +- Vendor Agent SDKs + - [openai-agents](https://github.com/openai/openai-agents-python) - OpenAI's framework for building and managing AI agents. +- Personal Assistants + - [hermes-agent](https://github.com/nousresearch/hermes-agent) - An adaptive personal AI assistant that grows with you. +- Prompt Optimization + - [dspy](https://github.com/stanfordnlp/dspy) - A framework for programming, not prompting, language models. - Data Layer - - [entroly](https://github.com/juyterman1000/entroly) - An auditable context control plane that optimizes prompt context, stabilizes cache prefixes, and verifies answers locally with WITNESS. - [instructor](https://github.com/567-labs/instructor) - A library for extracting structured data from LLMs, powered by Pydantic. - [llama-index](https://github.com/run-llama/llama_index) - A data framework for your LLM application. - - [lumen](https://github.com/holoviz/lumen) - An agent framework for conversational analysis of SQL, dataframe and multidimensional array data. - [mem0](https://github.com/mem0ai/mem0) - An intelligent memory layer for AI agents enabling personalized interactions. - - [outlines](https://github.com/dottxt-ai/outlines) - Structured text generation for LLMs with JSON schema, regex, and grammar-constrained decoding. -- Pre-trained Models and Inference - - [diffusers](https://github.com/huggingface/diffusers) - A library that provides pre-trained diffusion models for generating and editing images, audio, and video. - - [LiteLLM](https://github.com/BerriAI/litellm) - Call 100+ LLMs using OpenAI format. - - [liter-llm](https://github.com/xberg-io/liter-llm) - A universal LLM API client with a Rust core, calling 142+ providers through a single OpenAI-compatible interface, with a built-in proxy and MCP server. +- Pre-trained Models + - [transformers](https://github.com/huggingface/transformers) - A framework that lets you easily use pre-trained transformer models for NLP, vision, and audio tasks. +- LLM Inference and Serving - [mlx-lm](https://github.com/ml-explore/mlx-lm) - Run and fine-tune large language models on Apple Silicon with MLX. - [sglang](https://github.com/sgl-project/sglang) - A high-performance serving framework for large language models and multimodal models. - - [transformers](https://github.com/huggingface/transformers) - A framework that lets you easily use pre-trained transformer models for NLP, vision, and audio tasks. - - [unsloth](https://github.com/unslothai/unsloth) - A library for faster LLM fine-tuning and training with reduced memory usage. - [vllm](https://github.com/vllm-project/vllm) - A high-throughput and memory-efficient inference and serving engine for LLMs. +- LLM Gateways + - [LiteLLM](https://github.com/BerriAI/litellm) - Call 100+ LLMs using OpenAI format. +- Image and Video Generation + - [diffusers](https://github.com/huggingface/diffusers) - A library that provides pre-trained diffusion models for generating and editing images, audio, and video. +- Fine-tuning + - [unsloth](https://github.com/unslothai/unsloth) - A library for faster LLM fine-tuning and training with reduced memory usage. - Speech - [funasr](https://github.com/modelscope/FunASR) - Industrial-grade speech recognition toolkit with 170x realtime speed, 50+ languages, speaker diarization, and emotion detection. - [openai-whisper](https://github.com/openai/whisper) - A general-purpose automatic speech recognition model trained on 680k hours of multilingual and multitask supervised data. - - [SenseVoice](https://github.com/FunAudioLLM/SenseVoice) - A multilingual speech understanding model for speech recognition, language identification, emotion recognition, and audio event detection. - [vibevoice](https://github.com/microsoft/VibeVoice) - A family of open-source voice AI models from Microsoft for text-to-speech and long-form speech recognition. - - [voxcpm](https://github.com/OpenBMB/VoxCPM) - A tokenizer-free text-to-speech foundation model for multilingual speech generation and voice cloning. ### Deep Learning @@ -544,6 +532,7 @@ _Libraries for visualizing data. Also see [awesome-javascript](https://github.co - [vispy](https://github.com/vispy/vispy) - High-performance scientific visualization based on OpenGL. - Specialized - [cartopy](https://github.com/SciTools/cartopy) - A cartographic python library with matplotlib support. + - [graphify](https://github.com/safishamsi/graphify) - Turn any folder of code, SQL schemas, docs, papers, images, or videos into a queryable knowledge graph. - [pygraphviz](https://github.com/pygraphviz/pygraphviz/) - Python interface to [Graphviz](https://www.graphviz.org/). - Dashboards and Apps - [gradio](https://github.com/gradio-app/gradio) - Build and share machine learning apps, all in Python. From e4e70cd320cadeb5f9918d80cb665b9944a62799 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 14:36:52 +0800 Subject: [PATCH 010/168] feat: add claude-agent-sdk to Vendor Agent SDKs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anthropic's Python SDK for building AI agents on Claude Code's harness. ~32.6M downloads/month (pepy, 2026-08-15; approximate, includes mirrors — pypistats was rate-limited). Lands beside openai-agents in the Vendor Agent SDKs use case minted in the AI and Agents sweep. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f87a4ef6c3..5b6defb3da 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,7 @@ _Libraries for building AI applications, LLM integrations, and autonomous agents - [langgraph](https://github.com/langchain-ai/langgraph) - Low-level orchestration framework for building stateful, long-running LLM agents. - [pydantic-ai](https://github.com/pydantic/pydantic-ai) - A Python agent framework for building generative AI applications with structured schemas. - Vendor Agent SDKs + - [claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-python) - Anthropic's Python SDK for building AI agents on Claude Code's harness — custom tools, in-process MCP servers, hooks. - [openai-agents](https://github.com/openai/openai-agents-python) - OpenAI's framework for building and managing AI agents. - Personal Assistants - [hermes-agent](https://github.com/nousresearch/hermes-agent) - An adaptive personal AI assistant that grows with you. From 6cd5ffc5a39d1c5cb4e04857ee2042129b693975 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 14:39:33 +0800 Subject: [PATCH 011/168] prune: sweep File Format Processing to the shortlist cap Per ADR-0001, restructure first: split MS Office into Excel, Word, and PowerPoint; mint File Conversion (docling re-homed from General, markitdown re-homed from Markdown) and HTML-to-PDF (weasyprint re-homed from PDF). Then cap. xlsxwriter and weasyprint keep their slots via the Splits (decision reversing their earlier drop verdicts). Removed (downloads are PyPI last-month via pypistats, 2026-08-14/15): - xberg (26K/month): xberg-io coordinated self-promotion plant - xlwings (941K/month): different job (calling Python from Excel), not the Excel file-format use case - docxtpl: templating layer over python-docx, which holds the Word slot - pyexcel (2.2M/month): abstraction over the per-format libraries that hold the slots - pikepdf (10.6M/month): PDF use case at cap; pypdf, reportlab, and pdfminer.six are the obvious choices - pdf_oxide (142K/month): no adoption evidence against the incumbents - csvkit (506K/month): not the obvious choice for CSV work Co-Authored-By: Claude --- README.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 5b6defb3da..1d95a66ca6 100644 --- a/README.md +++ b/README.md @@ -919,32 +919,29 @@ _Libraries for working with HTML and XML._ _Libraries for parsing and manipulating specific text formats._ - General - - [docling](https://github.com/docling-project/docling) - Library for converting documents into structured data. - - [xberg](https://github.com/xberg-io/xberg) - High-performance document intelligence library with a Rust core, extracting text, tables, and metadata from 97+ formats including PDF, Office, images (with OCR), HTML, email, and archives. - [pyelftools](https://github.com/eliben/pyelftools) - Parsing and analyzing ELF files and DWARF debugging information. - [tablib](https://github.com/jazzband/tablib) - A module for Tabular Datasets in XLS, CSV, JSON, YAML. -- MS Office - - [docxtpl](https://github.com/elapouya/python-docx-template) - Editing a docx document by jinja2 template +- File Conversion + - [docling](https://github.com/docling-project/docling) - Library for converting documents into structured data. + - [markitdown](https://github.com/microsoft/markitdown) - Python tool for converting files and office documents to Markdown. +- Excel - [openpyxl](https://openpyxl.readthedocs.io/en/stable/) - A library for reading and writing Excel 2010 xlsx/xlsm/xltx/xltm files. - - [pyexcel](https://github.com/pyexcel/pyexcel) - Providing one API for reading, manipulating and writing csv, ods, xls, xlsx and xlsm files. + - [xlsxwriter](https://github.com/jmcnamara/XlsxWriter) - A Python module for creating Excel .xlsx files. +- Word - [python-docx](https://github.com/python-openxml/python-docx) - Reads, queries and modifies Microsoft Word 2007/2008 docx files. +- PowerPoint - [python-pptx](https://github.com/scanny/python-pptx) - Python library for creating and updating PowerPoint (.pptx) files. - - [xlsxwriter](https://github.com/jmcnamara/XlsxWriter) - A Python module for creating Excel .xlsx files. - - [xlwings](https://github.com/xlwings/xlwings) - A BSD-licensed library that makes it easy to call Python from Excel and vice versa. - PDF - - [pdf_oxide](https://github.com/yfedoseev/pdf_oxide) - A fast PDF library for text extraction, image extraction, and markdown conversion, powered by Rust. - [pdfminer.six](https://github.com/pdfminer/pdfminer.six) - Pdfminer.six is a community maintained fork of the original PDFMiner. - - [pikepdf](https://github.com/pikepdf/pikepdf) - A powerful library for reading and editing PDF files, based on qpdf. - [pypdf](https://github.com/py-pdf/pypdf) - A library capable of splitting, merging, cropping, and transforming PDF pages. - [reportlab](https://www.reportlab.com/opensource/) - Allowing Rapid creation of rich PDF documents. +- HTML-to-PDF - [weasyprint](https://github.com/Kozea/WeasyPrint) - A visual rendering engine for HTML and CSS that can export to PDF. - Markdown - - [markdown-it-py](https://github.com/executablebooks/markdown-it-py) - Markdown parser with 100% CommonMark support, extensions, and syntax plugins. - [markdown](https://github.com/Python-Markdown/markdown) - A Python implementation of John Gruber’s Markdown. - - [markitdown](https://github.com/microsoft/markitdown) - Python tool for converting files and office documents to Markdown. + - [markdown-it-py](https://github.com/executablebooks/markdown-it-py) - Markdown parser with 100% CommonMark support, extensions, and syntax plugins. - [mistune](https://github.com/lepture/mistune) - Fastest and full featured pure Python parsers of Markdown. - Data Formats - - [csvkit](https://github.com/wireservice/csvkit) - Utilities for converting to and working with CSV. - [pyyaml](https://github.com/yaml/pyyaml) - YAML implementations for Python. - [tomllib](https://docs.python.org/3/library/tomllib.html) - (Python standard library) Parse TOML files. From 5488d08db1b2c956f05f52d9a2b6aee073984b5c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 14:39:53 +0800 Subject: [PATCH 012/168] prune: sweep Data Visualization to the shortlist cap Per ADR-0001. No restructure needed: Plotting caps to matplotlib, plotly, seaborn plus altair as Challenger (listed last per the Challenger-ordering rule); Specialized (cartopy, graphify, pygraphviz) and Dashboards and Apps (gradio, streamlit) already fit. Removed (downloads are PyPI last-month via pypistats, 2026-08-14/15): - bokeh (8.4M/month): Plotting at cap; interactive plotting job covered by plotly - plotnine (3.1M/month): below the shortlist bar - vispy (1.4M/month): below the shortlist bar - pyqtgraph (1.0M/month): below the shortlist bar - bqplot (381K/month): below the shortlist bar - pygal: legacy; downloads fetch failed - ultraplot (3.9K/month): no adoption Co-Authored-By: Claude --- README.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/README.md b/README.md index 1d95a66ca6..2d189b9230 100644 --- a/README.md +++ b/README.md @@ -520,17 +520,10 @@ _Libraries for validating data. Used for forms in many cases._ _Libraries for visualizing data. Also see [awesome-javascript](https://github.com/sorrycc/awesome-javascript#data-visualization)._ - Plotting - - [altair](https://github.com/vega/altair) - Declarative statistical visualization library for Python. - - [bokeh](https://github.com/bokeh/bokeh) - Interactive Web Plotting for Python. - - [bqplot](https://github.com/bqplot/bqplot) - Interactive Plotting Library for the Jupyter Notebook. - [matplotlib](https://github.com/matplotlib/matplotlib) - A Python 2D plotting library. - [plotly](https://github.com/plotly/plotly.py) - Interactive graphing library for Python. - - [plotnine](https://github.com/has2k1/plotnine) - A grammar of graphics for Python based on ggplot2. - - [pygal](https://github.com/Kozea/pygal) - A Python SVG Charts Creator. - - [pyqtgraph](https://github.com/pyqtgraph/pyqtgraph) - Interactive and realtime 2D/3D/Image plotting and science/engineering widgets. - [seaborn](https://github.com/mwaskom/seaborn) - Statistical data visualization using Matplotlib. - - [ultraplot](https://github.com/ultraplot/UltraPlot) - Matplotlib wrapper for publication-ready scientific figures with minimal code. Includes advanced subplot management, panel layouts, and batteries-included geoscience plotting. - - [vispy](https://github.com/vispy/vispy) - High-performance scientific visualization based on OpenGL. + - [altair](https://github.com/vega/altair) - Declarative statistical visualization library for Python. - Specialized - [cartopy](https://github.com/SciTools/cartopy) - A cartographic python library with matplotlib support. - [graphify](https://github.com/safishamsi/graphify) - Turn any folder of code, SQL schemas, docs, papers, images, or videos into a queryable knowledge graph. From 5200ffa289f1fafb25d006bf614ece0deb811833 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 15:20:50 +0800 Subject: [PATCH 013/168] prune: sweep Testing to the shortlist cap Per ADR-0001, restructure first: split GUI / Web Testing into Browser Automation (playwright-python, selenium), Load Testing (locust), and API Testing (schemathesis). Then cap. Maintainer-adjudicated 2026-08-15 at the preview review: robotframework, schemathesis, respx, vcrpy, and mimesis keep against the old dry-run verdicts; respx and vcrpy take the two Mock Challenger slots, nox stays the Test Runners Challenger (listed after tox per the Challenger-ordering rule). Removed (downloads are PyPI last-month, fetched 2026-08-15): - scanapi (3.3K/month): near-zero usage - unittest: stdlib rule - a stdlib module survives only where it is itself the Obvious Choice; for test frameworks that is pytest - pyautogui (2.5M/month): desktop GUI automation, not web testing; no Use Case slot after the Split - mocket (273K/month): socket-level mocking; small audience next to responses Co-Authored-By: Claude --- README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2d189b9230..080b74850a 100644 --- a/README.md +++ b/README.md @@ -643,21 +643,19 @@ _Libraries for testing codebases and generating test data. Also see [awesome-pyt - [pytest](https://github.com/pytest-dev/pytest) - A mature full-featured Python testing tool. - [awesome-pytest](https://github.com/augustogoulart/awesome-pytest) - [robotframework](https://github.com/robotframework/robotframework) - A generic test automation framework. - - [scanapi](https://github.com/scanapi/scanapi) - Automated Testing and Documentation for your REST API. - - [unittest](https://docs.python.org/3/library/unittest.html) - (Python standard library) Unit testing framework. - Test Runners - - [nox](https://github.com/wntrblm/nox) - Flexible test automation for Python. - [tox](https://github.com/tox-dev/tox) - Auto builds and tests distributions in multiple Python versions -- GUI / Web Testing - - [locust](https://github.com/locustio/locust) - Scalable user load testing tool written in Python. + - [nox](https://github.com/wntrblm/nox) - Flexible test automation for Python. +- Browser Automation - [playwright-python](https://github.com/microsoft/playwright-python) - Python version of the Playwright testing and automation library. - - [pyautogui](https://github.com/asweigart/pyautogui) - PyAutoGUI is a cross-platform GUI automation Python module for human beings. - - [schemathesis](https://github.com/schemathesis/schemathesis) - A tool for automatic property-based testing of web applications built with Open API / Swagger specifications. - [selenium](https://github.com/SeleniumHQ/selenium) - Python bindings for [Selenium](https://selenium.dev/) [WebDriver](https://selenium.dev/documentation/webdriver/). +- Load Testing + - [locust](https://github.com/locustio/locust) - Scalable user load testing tool written in Python. +- API Testing + - [schemathesis](https://github.com/schemathesis/schemathesis) - A tool for automatic property-based testing of web applications built with Open API / Swagger specifications. - Mock - [freezegun](https://github.com/spulec/freezegun) - Travel through time by mocking the datetime module. - [mock](https://docs.python.org/3/library/unittest.mock.html) - (Python standard library) A mocking and patching library. - - [mocket](https://github.com/mindflayer/python-mocket) - A socket mock framework with gevent/asyncio/SSL support. - [responses](https://github.com/getsentry/responses) - A utility library for mocking out the requests Python library. - [respx](https://github.com/lundberg/respx) - Mock HTTPX with awesome request patterns and response side effects. - [vcrpy](https://github.com/kevin1024/vcrpy) - Record and replay HTTP interactions on your tests. From b0cdf402eb7aeba8374b8f8e59bf431fc56eb56e Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 15:27:16 +0800 Subject: [PATCH 014/168] feat: add verdict-preview skill for maintainer review pages Adds a reusable skill that generates the interactive keep/drop review page (seeded verdicts + reasons, maintainer Keep/Drop toggles and reason fields, JSON feedback export) and processes the pasted feedback, so every future prune sweep or batch entry edit reuses the pattern proven in the shortlist-reform reviews. Removes .claude/skills/ and the dead .agents/ line from .gitignore so the skill is tracked, per maintainer direction. Co-Authored-By: Claude --- .claude/skills/verdict-preview/SKILL.md | 24 +++ .claude/skills/verdict-preview/template.html | 160 +++++++++++++++++++ .gitignore | 2 - 3 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 .claude/skills/verdict-preview/SKILL.md create mode 100644 .claude/skills/verdict-preview/template.html diff --git a/.claude/skills/verdict-preview/SKILL.md b/.claude/skills/verdict-preview/SKILL.md new file mode 100644 index 0000000000..1572abc589 --- /dev/null +++ b/.claude/skills/verdict-preview/SKILL.md @@ -0,0 +1,24 @@ +--- +name: verdict-preview +description: Generate the interactive keep/drop verdict preview (HTML page with per-row feedback controls) whenever a prune sweep, batch entry edit, or restructure needs maintainer review before touching README.md — and process the feedback JSON the maintainer pastes back. +--- + +# Verdict preview + +Maintainer review happens through an interactive HTML page: one row per entry with your seeded verdict and reason, a Keep/Drop toggle and a reason field for the maintainer, and a **Copy feedback** button that exports only changed or commented rows as JSON. Generate the page, wait for the pasted JSON, then apply it. Entry changes land in README.md only after the review — and only on an explicit go. + +## Generate the preview + +1. Build the `DATA` array. A group is `[section, subcategory, rows]`; a row is `[entry, url, downloads, verdict, reason]`. + - `subcategory` may carry a note after ` — ` (rendered muted): use it for proposed splits, re-homes, or anything the maintainer should weigh for the whole group. + - `downloads` is PyPI last-month as a comma-formatted string; use `—` when no signal exists (e.g. agent skill packs), `stdlib` for standard-library modules, `fetch failed` when the lookup failed. State the fetch date in the sub-header. + - `verdict` is `keep` or `drop`, seeded from the current adjudication or dry-run. + - `reason` is plain language the maintainer reads cold — no invented shorthand. When fresh evidence contradicts the seeded verdict (a big download count on a drop, a dead repo on a keep), say so in that row's reason instead of silently changing the seed. +2. Copy `template.html` (sibling of this file) and replace the placeholders: `__TITLE__` (page title), `__SUB__` (sub-header: scope, seed provenance, fetch date, and the standing instruction to flip/comment then Copy feedback), `__KEY__` (localStorage key), `__DATA__` (the array). `__KEY__` must be unique per review — slug plus date, e.g. `awesome-python-science-2026-09-01` — because saved state under a reused key bleeds a previous review's flips into rows with the same section and entry name. +3. Write the page to `/tmp/awesome-python--preview.html`, `open` it, and tell the maintainer the path and the return path: flip or comment rows (they highlight yellow), press **Copy feedback**, paste the JSON into the chat. Done when the page is open and the return path is stated. + +## Process the pasted feedback + +Each JSON row is `{section, subcategory, entry, my_verdict, your_verdict, reason}`. The maintainer's verdict is final — apply it, never re-argue it. An empty reason means the verdict stands unexplained; that is enough. + +Before executing, surface anything the flips imply that the maintainer has not decided: a use case pushed past its cap, an entry left homeless by a proposed split, a request that is already satisfied (a no-op). Ask, then execute on their go. Done when every pasted row is either applied or surfaced back — none silently dropped. diff --git a/.claude/skills/verdict-preview/template.html b/.claude/skills/verdict-preview/template.html new file mode 100644 index 0000000000..91324e82f4 --- /dev/null +++ b/.claude/skills/verdict-preview/template.html @@ -0,0 +1,160 @@ + + + + + +__TITLE__ + + + +
+

__TITLE__

+

__SUB__

+
+ +
+
+ + + Copies only rows you changed or commented, as JSON. +
+ + + diff --git a/.gitignore b/.gitignore index 5fbd39f128..ab400a0226 100644 --- a/.gitignore +++ b/.gitignore @@ -18,8 +18,6 @@ docs/* !docs/adr/ # agents -.agents/ -.claude/skills/ .superpowers/ .playwright-cli/ skills-lock.json From fc88ebb89997fcf04c78e8e6776b944bdf4e7ba7 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 15:41:55 +0800 Subject: [PATCH 015/168] feat: add BigQuery-based PyPI downloads fetcher Provides per-sitting download evidence for prune sweeps, per the shortlist-reform tooling plan. Shells out to the bq CLI against bigquery-public-data.pypi.file_downloads, parses entry names from README.md via readme_parser, and supports --dry-run and --names-file. Merges results into the gitignored cache at website/data/pypi_downloads.tsv. The table is clustered on file.project, so scanned bytes grow with the IN-list size: a dry run against the full README (~530 names) scanned 1.21 TB, past the 1 TB/month free tier. Per-sitting --names-file fetches are used instead of one big query. Co-Authored-By: Claude --- website/fetch_pypi_downloads.py | 94 +++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 website/fetch_pypi_downloads.py diff --git a/website/fetch_pypi_downloads.py b/website/fetch_pypi_downloads.py new file mode 100644 index 0000000000..e79c3620ea --- /dev/null +++ b/website/fetch_pypi_downloads.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +"""Fetch last-30-day PyPI download counts for README entries via BigQuery. + +Shells out to the `bq` CLI (Google Cloud SDK) against the public +`bigquery-public-data.pypi.file_downloads` table. The table is clustered on +file.project, so scanned bytes grow with the IN-list: a few dozen names +prune to tens of GB while the full README (~530 names) balloons to over +1 TB — past the free tier. Fetch per curation sitting with --names-file +instead of all at once. Results are cached to data/pypi_downloads.tsv +(merged with any existing rows); names with no PyPI rows are written as +NOT_FOUND. Always --dry-run first to check the scan estimate. + +Usage: python fetch_pypi_downloads.py [--dry-run] [--names-file FILE] +""" + +import re +import subprocess +import sys +from json import loads +from pathlib import Path + +from readme_parser import parse_readme + +DATA_DIR = Path(__file__).parent / "data" +OUT_FILE = DATA_DIR / "pypi_downloads.tsv" +README_PATH = Path(__file__).parent.parent / "README.md" + +# PyPI normalizes names to lowercase with runs of -, _, . collapsed to -. +PYPI_NAME_RE = re.compile(r"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$") + + +def normalize(name: str) -> str: + return re.sub(r"[-_.]+", "-", name.lower()) + + +def collect_names(readme_text: str) -> list[str]: + names = set() + for group in parse_readme(readme_text): + for section in group["categories"]: + for entry in section["entries"]: + normalized = normalize(entry["name"]) + if PYPI_NAME_RE.match(normalized): + names.add(normalized) + return sorted(names) + + +def fetch(names: list[str], dry_run: bool) -> dict[str, int]: + in_list = ", ".join(f"'{name}'" for name in names) + query = ( + "SELECT file.project AS project, COUNT(*) AS downloads " + "FROM `bigquery-public-data.pypi.file_downloads` " + "WHERE DATE(timestamp) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) " + "AND CURRENT_DATE() " + f"AND file.project IN ({in_list}) " + "GROUP BY file.project" + ) + cmd = ["bq", "query", "--use_legacy_sql=false", "--format=json"] + if dry_run: + cmd.append("--dry_run") + cmd.append(query) + result = subprocess.run(cmd, capture_output=True, text=True) + if result.returncode != 0: + print(result.stderr, file=sys.stderr) + sys.exit(1) + if dry_run: + print(result.stdout.strip() or result.stderr.strip()) + sys.exit(0) + rows = loads(result.stdout) + return {row["project"]: int(row["downloads"]) for row in rows} + + +def main() -> None: + dry_run = "--dry-run" in sys.argv + if "--names-file" in sys.argv: + names_path = Path(sys.argv[sys.argv.index("--names-file") + 1]) + names = sorted({normalize(line) for line in names_path.read_text().split() if line}) + else: + names = collect_names(README_PATH.read_text()) + print(f"Querying {len(names)} package names...") + counts = fetch(names, dry_run) + merged: dict[str, str] = {} + if OUT_FILE.exists(): + for line in OUT_FILE.read_text().splitlines(): + name, _, value = line.partition("\t") + merged[name] = value + for name in names: + merged[name] = str(counts.get(name, "NOT_FOUND")) + OUT_FILE.write_text("\n".join(f"{name}\t{value}" for name, value in sorted(merged.items())) + "\n") + found = sum(1 for name in names if name in counts) + print(f"Done. {found}/{len(names)} names found on PyPI. Cached to {OUT_FILE}") + + +if __name__ == "__main__": + main() From bb53dfea9d723f1d14391bf8f5fde51af7fc5ba0 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 23:31:34 +0800 Subject: [PATCH 016/168] docs: require live verification of keep/drop reasons Qualitative keep/drop reasoning previously relied on training-data recollections that went unverified while only download numbers were checked live, as happened in the Data & Science preview. Key Rules now require every keep/drop reason to be verified against current online data at decision time. Co-Authored-By: Claude --- CLAUDE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CLAUDE.md b/CLAUDE.md index 402cf791ff..a951543bab 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -28,4 +28,5 @@ An opinionated list of Python frameworks, libraries, tools, and resources. Publi - A shortlist, not a catalog: per use case, up to 3 obvious choices plus up to 2 challengers, hard maximum 5. - One project per PR. - One entry per commit when adding or deleting entries. Exception: a prune sweep is one commit per section, its body listing each removal with its reason. Format, wording, or categorization changes across multiple entries may be bundled in a single commit. +- Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Training-data recollections alone are not evidence; verify before stating, and label anything unverifiable as a judgment call. - README.md is the single source of content truth. From 3ae3483d3626dbd618969f379266360d652051e1 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 23:53:12 +0800 Subject: [PATCH 017/168] docs: reinstate crewai in AI and Agents orchestration Re-added as a Challenger alongside pydantic-ai. The maintainer reviewed the committed-drops audit (all 36 removals re-verified against live data 2026-08-15) and flipped crewai back: 19.4M downloads/month, 57.1K stars, repo active same-day. The original 'buzz peaked' drop was judgment the audit data did not support. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 080b74850a..ada818a554 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,7 @@ _Libraries for building AI applications, LLM integrations, and autonomous agents - Orchestration - [langchain](https://github.com/langchain-ai/langchain) - Building applications with LLMs through composability. - [langgraph](https://github.com/langchain-ai/langgraph) - Low-level orchestration framework for building stateful, long-running LLM agents. + - [crewai](https://github.com/crewAIInc/crewAI) - A framework for orchestrating role-playing autonomous AI agents for collaborative task solving. - [pydantic-ai](https://github.com/pydantic/pydantic-ai) - A Python agent framework for building generative AI applications with structured schemas. - Vendor Agent SDKs - [claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-python) - Anthropic's Python SDK for building AI agents on Claude Code's harness — custom tools, in-process MCP servers, hooks. From 9290f1815302c6247b5109106c05277d130470dd Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 23:53:46 +0800 Subject: [PATCH 018/168] feat: reinstate bokeh as Plotting challenger The maintainer re-verified all 36 removals from the committed-drops audit against live data on 2026-08-15 and flipped bokeh back: 8.4M downloads/month, 20.4K stars, repo pushed the same day, the healthiest project among all audited drops. Placed as the second Challenger after altair, bringing Plotting to the hard max of 5 entries. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ada818a554..1951589911 100644 --- a/README.md +++ b/README.md @@ -525,6 +525,7 @@ _Libraries for visualizing data. Also see [awesome-javascript](https://github.co - [plotly](https://github.com/plotly/plotly.py) - Interactive graphing library for Python. - [seaborn](https://github.com/mwaskom/seaborn) - Statistical data visualization using Matplotlib. - [altair](https://github.com/vega/altair) - Declarative statistical visualization library for Python. + - [bokeh](https://github.com/bokeh/bokeh) - Interactive Web Plotting for Python. - Specialized - [cartopy](https://github.com/SciTools/cartopy) - A cartographic python library with matplotlib support. - [graphify](https://github.com/safishamsi/graphify) - Turn any folder of code, SQL schemas, docs, papers, images, or videos into a queryable knowledge graph. From 1463ba82867787ce8eb3f83a10deb3a70a1e401d Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 23:57:39 +0800 Subject: [PATCH 019/168] prune: sweep Data Analysis to the shortlist cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per ADR-0001, maintainer-adjudicated at the Data & Science preview review (2026-08-15, all rows live-verified). Keeps: pandas and polars as Obvious Choices, ibis as Challenger — renamed to ibis-framework per the PyPI-name convention (maintainer-confirmed; bare 'ibis' on PyPI is an unrelated template engine). aws-sdk-pandas returns as a sub-item under pandas per maintainer direction (sub-items sit outside the cap, awesome-pytest pattern). Removed (downloads are PyPI last-30-days via BigQuery, 2026-08-15): - data-profiling (18.2K/month under fg-data-profiling): YData's profiler, but the listed name is not on PyPI and a profiling layer is not an obvious choice for this use case - datasette (178.6K/month): data publishing and exploration tool, a different job - desbordante (3.4K/month): no adoption - modin (1.6M/month): the pandas-at-scale job moved to polars and dask; repo quiet since 2026-02 - pathway (16.5K/month): stars far ahead of usage (62.5K stars); ETL job, mis-homed here - percentify (182.2K/month): personal project, 11-month-old repo, 418 stars — count not credible against the footprint Co-Authored-By: Claude --- README.md | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1951589911..605c073c90 100644 --- a/README.md +++ b/README.md @@ -480,18 +480,10 @@ _Libraries for serializing complex data types._ _Libraries for data analysis._ -- [aws-sdk-pandas](https://github.com/aws/aws-sdk-pandas) - Pandas on AWS. -- [data-profiling](https://github.com/Data-Centric-AI-Community/fg-data-profiling) - Generate detailed data profiling reports for pandas DataFrames. -- [datasette](https://github.com/simonw/datasette) - An open source multi-tool for exploring and publishing data. -- [desbordante](https://github.com/desbordante/desbordante-core/) - An open source data profiler for complex pattern discovery. -- [ibis](https://github.com/ibis-project/ibis) - A portable Python dataframe library with a single API for 20+ backends. -- [modin](https://github.com/modin-project/modin) - A drop-in pandas replacement that scales workflows by changing a single line of code. - [pandas](https://github.com/pandas-dev/pandas) - A library providing high-performance, easy-to-use data structures and data analysis tools. -- [pathway](https://github.com/pathwaycom/pathway) - Real-time data processing framework for Python with reactive dataflows. - -- [percentify](https://github.com/data-centt/percentify) - Exploratory stats and data-quality diagnostics/profiler, that supports both pandas and Polars DataFrames inputs. - + - [aws-sdk-pandas](https://github.com/aws/aws-sdk-pandas) - [polars](https://github.com/pola-rs/polars) - A fast DataFrame library implemented in Rust with a Python API. +- [ibis-framework](https://github.com/ibis-project/ibis) - A portable Python dataframe library with a single API for 20+ backends. ### Data Ingestion / ETL From 54c0c0c34afc331be441ba4c32fbd59ffdfbe7d5 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 23:57:55 +0800 Subject: [PATCH 020/168] prune: sweep Data Ingestion / ETL to the shortlist cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per ADR-0001, maintainer-adjudicated at the Data & Science preview review (2026-08-15, all rows live-verified). General keeps dlt (sole entry). Financial Data keeps akshare and yfinance as Obvious Choices with edgartools and openbb as Challengers (openbb on the platform judgment: 71.9K stars against 132K pip installs). Removed (downloads are PyPI last-30-days via BigQuery, 2026-08-15): - lumibot (168.2K/month): algorithmic trading and backtesting framework with broker execution — not financial data; vertical app (TradingAgents precedent) Co-Authored-By: Claude --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 605c073c90..d5c23f3949 100644 --- a/README.md +++ b/README.md @@ -493,10 +493,9 @@ _Libraries for data extraction, transformation, and loading pipelines across mul - [dlt](https://github.com/dlt-hub/dlt) - A Python library for building data pipelines with automatic schema inference, incremental loading, and support for multiple sources and destinations. - Financial Data - [akshare](https://github.com/akfamily/akshare) - A financial data interface library, built for human beings! + - [yfinance](https://github.com/ranaroussi/yfinance) - Easy Pythonic way to download market and financial data from Yahoo Finance. - [edgartools](https://github.com/dgunning/edgartools) - Library for downloading structured data from SEC EDGAR filings and XBRL financial statements. - - [lumibot](https://github.com/Lumiwealth/lumibot) - Algorithmic trading framework for backtesting and live deployment across stocks, options, crypto, futures, and forex. - [openbb](https://github.com/OpenBB-finance/OpenBB) - A financial data platform for analysts, quants and AI agents. - - [yfinance](https://github.com/ranaroussi/yfinance) - Easy Pythonic way to download market and financial data from Yahoo Finance. ### Data Validation From 9103f59cbb50189043a9a0f43f0f86d9118cce3a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 23:58:22 +0800 Subject: [PATCH 021/168] prune: sweep Data Validation to the shortlist cap Per ADR-0001, maintainer-adjudicated at the Data & Science preview review (2026-08-15, all rows live-verified). Keeps jsonschema, pandera, and pydantic as Obvious Choices for their distinct validation jobs. Removed (downloads are PyPI last-30-days via BigQuery, 2026-08-15): - cerberus (6.7M/month): pre-pydantic era passed; repo alive but slow - voluptuous (8.0M/month): pre-pydantic era passed; repo description opens with "CONTRIBUTIONS ONLY" (maintenance mode) Co-Authored-By: Claude --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index d5c23f3949..d2a051c244 100644 --- a/README.md +++ b/README.md @@ -501,11 +501,9 @@ _Libraries for data extraction, transformation, and loading pipelines across mul _Libraries for validating data. Used for forms in many cases._ -- [cerberus](https://github.com/pyeve/cerberus) - A lightweight and extensible data validation library. - [jsonschema](https://github.com/python-jsonschema/jsonschema) - An implementation of [JSON Schema](https://json-schema.org/) for Python. - [pandera](https://github.com/unionai-oss/pandera) - A data validation library for dataframes, with support for pandas, polars, and Spark. - [pydantic](https://github.com/pydantic/pydantic) - Data validation using Python type hints. -- [voluptuous](https://github.com/alecthomas/voluptuous) - A Python data validation library primarily intended for validating data from untrusted sources. ### Data Visualization From 9631207f543eb2379f59a351c8118fee30524b6b Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 23:58:37 +0800 Subject: [PATCH 022/168] prune: sweep Geolocation to the shortlist cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per ADR-0001, maintainer-adjudicated at the Data & Science preview review (2026-08-15, all rows live-verified). Keeps geojson, geopandas, and geopy as Obvious Choices; geodjango kept by maintainer flip and listed last as Challenger (the cap allows three obvious choices). Removed (downloads are PyPI last-30-days via BigQuery, 2026-08-15): - django-countries (2.3M/month): country choices for Django forms and models — Django form tooling, not geolocation work Co-Authored-By: Claude --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index d2a051c244..2e681ebbdf 100644 --- a/README.md +++ b/README.md @@ -527,11 +527,10 @@ _Libraries for visualizing data. Also see [awesome-javascript](https://github.co _Libraries for geocoding addresses and working with latitudes and longitudes._ -- [django-countries](https://github.com/SmileyChris/django-countries) - A Django app that provides a country field for models and forms. -- [geodjango](https://github.com/django/django) - A world-class geographic web framework that is part of [Django](https://docs.djangoproject.com/en/dev/ref/contrib/gis/). - [geojson](https://github.com/jazzband/geojson) - Python bindings and utilities for GeoJSON. - [geopandas](https://github.com/geopandas/geopandas) - Python tools for geographic data (GeoSeries/GeoDataFrame) built on pandas. - [geopy](https://github.com/geopy/geopy) - Python Geocoding Toolbox. +- [geodjango](https://github.com/django/django) - A world-class geographic web framework that is part of [Django](https://docs.djangoproject.com/en/dev/ref/contrib/gis/). ### Science From 0c1409dea85ff2167f784ba251f2f20a28a17944 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 23:59:05 +0800 Subject: [PATCH 023/168] prune: sweep Science to the shortlist cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per ADR-0001, maintainer-adjudicated at the Data & Science preview review (2026-08-15, all rows live-verified). Restructure first: Core narrows to numba, numpy, scipy; mint Symbolic Mathematics (sympy), Statistics (statsmodels), Graphs and Networks (networkx), and Computational Geometry (shapely) — five co-obvious tools doing five different jobs, the decision-13 pattern. Other shrinks to a two-entry grab-bag; colour renamed to colour-science per the PyPI-name convention (bare 'colour' on PyPI is an unrelated color-conversion library). Then cap. Removed (downloads are PyPI last-30-days via BigQuery, 2026-08-15): - cclib (29.7K/month): computational-chemistry log parsing, small audience - openbabel (54.9K/month pip; conda-forge adds only 1.8M all-time): legacy toolbox next to rdkit - pydy (1.2K/month): near-zero usage - PythonRobotics: educational algorithm compilation ("sample codes and textbook" per its own description), not a library; not on PyPI - pathsim (6.3K/month): no adoption Co-Authored-By: Claude --- README.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 2e681ebbdf..7b836c3078 100644 --- a/README.md +++ b/README.md @@ -540,28 +540,27 @@ _Libraries for scientific computing. Also see [Python-for-Scientists](https://gi - [numba](https://github.com/numba/numba) - Python JIT compiler to LLVM aimed at scientific Python. - [numpy](https://github.com/numpy/numpy) - A fundamental package for scientific computing with Python. - [scipy](https://github.com/scipy/scipy) - A Python-based ecosystem of open-source software for mathematics, science, and engineering. - - [statsmodels](https://github.com/statsmodels/statsmodels) - Statistical modeling and econometrics in Python. +- Symbolic Mathematics - [sympy](https://github.com/sympy/sympy) - A Python library for symbolic mathematics. +- Statistics + - [statsmodels](https://github.com/statsmodels/statsmodels) - Statistical modeling and econometrics in Python. - Biology and Chemistry - [biopython](https://github.com/biopython/biopython) - Biopython is a set of freely available tools for biological computation. - - [cclib](https://github.com/cclib/cclib) - A library for parsing and interpreting the results of computational chemistry packages. - - [openbabel](https://github.com/openbabel/openbabel) - A chemical toolbox designed to speak the many languages of chemical data. - [rdkit](https://github.com/rdkit/rdkit) - Cheminformatics and Machine Learning Software. - Physics and Engineering - [astropy](https://github.com/astropy/astropy) - A community Python library for Astronomy. - [obspy](https://github.com/obspy/obspy) - A Python toolbox for seismology. - - [pydy](https://github.com/pydy/pydy) - Short for Python Dynamics, used to assist with workflow in the modeling of dynamic motion. - - [PythonRobotics](https://github.com/AtsushiSakai/PythonRobotics) - This is a compilation of various robotics algorithms with visualizations. - Simulation and Modeling - [mesa](https://github.com/mesa/mesa) - An agent-based modeling framework for building, analyzing, and visualizing complex system simulations. - - [pathsim](https://github.com/pathsim/pathsim) - A block-based system modeling and simulation framework with a browser-based visual editor. - [pymc](https://github.com/pymc-devs/pymc) - Probabilistic programming and Bayesian modeling in Python. - [simpy](https://gitlab.com/team-simpy/simpy) - A process-based discrete-event simulation framework. -- Other - - [colour](https://github.com/colour-science/colour) - Implementing a comprehensive number of colour theory transformations and algorithms. - - [manim](https://github.com/ManimCommunity/manim) - An animation engine for explanatory math videos. +- Graphs and Networks - [networkx](https://github.com/networkx/networkx) - A high-productivity software for complex networks. +- Computational Geometry - [shapely](https://github.com/shapely/shapely) - Manipulation and analysis of geometric objects in the Cartesian plane. +- Other + - [colour-science](https://github.com/colour-science/colour) - Implementing a comprehensive number of colour theory transformations and algorithms. + - [manim](https://github.com/ManimCommunity/manim) - An animation engine for explanatory math videos. ### Quantum Computing From c9abd51467e3ffa4f86f325401da3d0754270ec4 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sat, 15 Aug 2026 23:59:21 +0800 Subject: [PATCH 024/168] style: apply challenger ordering and entry format to Quantum Computing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per ADR-0001, maintainer-adjudicated at the Data & Science preview review (2026-08-15). No removals — all four entries keep: qiskit and qutip as Obvious Choices (circuit SDK and quantum physics simulation, distinct jobs), cirq and pennylane as Challengers, ordered per the Challenger-ordering rule. Format fixes bundled per the Key Rules bundling exception: three em-dash separators normalized to hyphens, Cirq lowercased to its PyPI name. Co-Authored-By: Claude --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7b836c3078..dfb968d705 100644 --- a/README.md +++ b/README.md @@ -566,10 +566,10 @@ _Libraries for scientific computing. Also see [Python-for-Scientists](https://gi _Libraries for quantum computing._ -- [Cirq](https://github.com/quantumlib/Cirq) — A Google-developed framework focused on hardware-aware quantum circuit design for NISQ devices. -- [pennylane](https://github.com/PennyLaneAI/pennylane) — A hybrid quantum-classical machine learning library with automatic differentiation support. -- [qiskit](https://github.com/Qiskit/qiskit) — An IBM-backed quantum SDK for building, simulating, and running circuits on real quantum hardware. +- [qiskit](https://github.com/Qiskit/qiskit) - An IBM-backed quantum SDK for building, simulating, and running circuits on real quantum hardware. - [qutip](https://github.com/qutip/qutip) - Quantum Toolbox in Python. +- [cirq](https://github.com/quantumlib/Cirq) - A Google-developed framework focused on hardware-aware quantum circuit design for NISQ devices. +- [pennylane](https://github.com/PennyLaneAI/pennylane) - A hybrid quantum-classical machine learning library with automatic differentiation support. **Developer Tools** From 846a6bdb91dfcc1bfb5f42efa67be176ad918d37 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 00:02:30 +0800 Subject: [PATCH 025/168] docs: order entries by downloads/month within tiers, not alphabetically Maintainer decision 2026-08-16, amending the ordering half of the Challenger-marking rule: within a use case, obvious choices still come first and challengers still follow (position stays the marker), but each tier now orders by PyPI downloads per month descending instead of alphabetically. Entries without a download signal (stdlib modules, agent skill packs) sort last within their tier, alphabetically. Updated in CONTRIBUTING.md (Entry Ordering), CONTEXT.md (Challenger), and CLAUDE.md (Key Rules). Co-Authored-By: Claude --- CLAUDE.md | 2 +- CONTEXT.md | 2 +- CONTRIBUTING.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a951543bab..da1c684b89 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,7 +24,7 @@ An opinionated list of Python frameworks, libraries, tools, and resources. Publi ## Key Rules -- Ordering within a use case: obvious choices first (alphabetically), then challengers (alphabetically). See CONTRIBUTING.md. +- Ordering within a use case: obvious choices first, then challengers, each tier by PyPI downloads/month descending; no-signal entries last in tier, alphabetically. See CONTRIBUTING.md. - A shortlist, not a catalog: per use case, up to 3 obvious choices plus up to 2 challengers, hard maximum 5. - One project per PR. - One entry per commit when adding or deleting entries. Exception: a prune sweep is one commit per section, its body listing each removal with its reason. Format, wording, or categorization changes across multiple entries may be bundled in a single commit. diff --git a/CONTEXT.md b/CONTEXT.md index d89804b31a..cab584e16c 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -41,7 +41,7 @@ The only admission path into a full Use Case: the PR names the entry it replaces _Avoid_: One-in-one-out (informal alias) **Challenger**: -An entry (at most two per Use Case) that is not yet the Obvious Choice but is a credible successor to one. Marked by ordering, not description: within a Use Case, Obvious Choices are listed first (alphabetically), then Challengers (alphabetically). Admission requires adoption-trajectory evidence, not popularity alone. +An entry (at most two per Use Case) that is not yet the Obvious Choice but is a credible successor to one. Marked by ordering, not description: within a Use Case, Obvious Choices are listed first, then Challengers, each tier by PyPI downloads/month descending (no-signal entries last in tier, alphabetically). Admission requires adoption-trajectory evidence, not popularity alone. _Avoid_: Rising Star (old lane name), Hidden Gem (old lane name — concept removed entirely) **Split**: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2367c766a5..c16c0a3bb9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,7 +73,7 @@ Use the **PyPI package name** as the display name so developers can copy it dire ### Entry Ordering -Within a use case, the obvious choices are listed first, alphabetically; challengers follow, alphabetically. There is no marker in the entry text — position is the marker, so the last entries of a use case may be its challengers. +Within a use case, the obvious choices are listed first, ordered by PyPI downloads per month from high to low; challengers follow, in the same order. Entries without a download signal (standard-library modules, agent skill packs) sort last within their tier, alphabetically. There is no marker in the entry text — position is the marker, so the last entries of a use case may be its challengers. ## Changing the Structure From 46b7b57d6b52f3af498c787c3ce6559a8de5b1c4 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 00:03:46 +0800 Subject: [PATCH 026/168] style: reorder swept sections by downloads/month within tiers Apply the new ordering rule (downloads/month descending within each tier, no-signal entries last alphabetically) to all ten swept sections. Sixteen use cases change order: Vendor Agent SDKs, LLM Inference and Serving, Speech, File Conversion, PDF, Markdown, Data Visualization Specialized and Dashboards, Testing Frameworks and Mock, Financial Data, Data Validation, Geolocation, Science Core and Simulation and Modeling, Quantum Computing challengers. Unswept sections keep their current order until their own sweeps. Bundled as a single categorization commit per the Key Rules bundling exception. Co-Authored-By: Claude --- README.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index dfb968d705..0857aed49e 100644 --- a/README.md +++ b/README.md @@ -142,8 +142,8 @@ _Libraries for building AI applications, LLM integrations, and autonomous agents - [crewai](https://github.com/crewAIInc/crewAI) - A framework for orchestrating role-playing autonomous AI agents for collaborative task solving. - [pydantic-ai](https://github.com/pydantic/pydantic-ai) - A Python agent framework for building generative AI applications with structured schemas. - Vendor Agent SDKs - - [claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-python) - Anthropic's Python SDK for building AI agents on Claude Code's harness — custom tools, in-process MCP servers, hooks. - [openai-agents](https://github.com/openai/openai-agents-python) - OpenAI's framework for building and managing AI agents. + - [claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-python) - Anthropic's Python SDK for building AI agents on Claude Code's harness — custom tools, in-process MCP servers, hooks. - Personal Assistants - [hermes-agent](https://github.com/nousresearch/hermes-agent) - An adaptive personal AI assistant that grows with you. - Prompt Optimization @@ -155,9 +155,9 @@ _Libraries for building AI applications, LLM integrations, and autonomous agents - Pre-trained Models - [transformers](https://github.com/huggingface/transformers) - A framework that lets you easily use pre-trained transformer models for NLP, vision, and audio tasks. - LLM Inference and Serving - - [mlx-lm](https://github.com/ml-explore/mlx-lm) - Run and fine-tune large language models on Apple Silicon with MLX. - [sglang](https://github.com/sgl-project/sglang) - A high-performance serving framework for large language models and multimodal models. - [vllm](https://github.com/vllm-project/vllm) - A high-throughput and memory-efficient inference and serving engine for LLMs. + - [mlx-lm](https://github.com/ml-explore/mlx-lm) - Run and fine-tune large language models on Apple Silicon with MLX. - LLM Gateways - [LiteLLM](https://github.com/BerriAI/litellm) - Call 100+ LLMs using OpenAI format. - Image and Video Generation @@ -165,8 +165,8 @@ _Libraries for building AI applications, LLM integrations, and autonomous agents - Fine-tuning - [unsloth](https://github.com/unslothai/unsloth) - A library for faster LLM fine-tuning and training with reduced memory usage. - Speech - - [funasr](https://github.com/modelscope/FunASR) - Industrial-grade speech recognition toolkit with 170x realtime speed, 50+ languages, speaker diarization, and emotion detection. - [openai-whisper](https://github.com/openai/whisper) - A general-purpose automatic speech recognition model trained on 680k hours of multilingual and multitask supervised data. + - [funasr](https://github.com/modelscope/FunASR) - Industrial-grade speech recognition toolkit with 170x realtime speed, 50+ languages, speaker diarization, and emotion detection. - [vibevoice](https://github.com/microsoft/VibeVoice) - A family of open-source voice AI models from Microsoft for text-to-speech and long-form speech recognition. ### Deep Learning @@ -492,8 +492,8 @@ _Libraries for data extraction, transformation, and loading pipelines across mul - General - [dlt](https://github.com/dlt-hub/dlt) - A Python library for building data pipelines with automatic schema inference, incremental loading, and support for multiple sources and destinations. - Financial Data - - [akshare](https://github.com/akfamily/akshare) - A financial data interface library, built for human beings! - [yfinance](https://github.com/ranaroussi/yfinance) - Easy Pythonic way to download market and financial data from Yahoo Finance. + - [akshare](https://github.com/akfamily/akshare) - A financial data interface library, built for human beings! - [edgartools](https://github.com/dgunning/edgartools) - Library for downloading structured data from SEC EDGAR filings and XBRL financial statements. - [openbb](https://github.com/OpenBB-finance/OpenBB) - A financial data platform for analysts, quants and AI agents. @@ -501,9 +501,9 @@ _Libraries for data extraction, transformation, and loading pipelines across mul _Libraries for validating data. Used for forms in many cases._ +- [pydantic](https://github.com/pydantic/pydantic) - Data validation using Python type hints. - [jsonschema](https://github.com/python-jsonschema/jsonschema) - An implementation of [JSON Schema](https://json-schema.org/) for Python. - [pandera](https://github.com/unionai-oss/pandera) - A data validation library for dataframes, with support for pandas, polars, and Spark. -- [pydantic](https://github.com/pydantic/pydantic) - Data validation using Python type hints. ### Data Visualization @@ -517,19 +517,19 @@ _Libraries for visualizing data. Also see [awesome-javascript](https://github.co - [bokeh](https://github.com/bokeh/bokeh) - Interactive Web Plotting for Python. - Specialized - [cartopy](https://github.com/SciTools/cartopy) - A cartographic python library with matplotlib support. - - [graphify](https://github.com/safishamsi/graphify) - Turn any folder of code, SQL schemas, docs, papers, images, or videos into a queryable knowledge graph. - [pygraphviz](https://github.com/pygraphviz/pygraphviz/) - Python interface to [Graphviz](https://www.graphviz.org/). + - [graphify](https://github.com/safishamsi/graphify) - Turn any folder of code, SQL schemas, docs, papers, images, or videos into a queryable knowledge graph. - Dashboards and Apps - - [gradio](https://github.com/gradio-app/gradio) - Build and share machine learning apps, all in Python. - [streamlit](https://github.com/streamlit/streamlit) - A framework which lets you build dashboards, generate reports, or create chat apps in minutes. + - [gradio](https://github.com/gradio-app/gradio) - Build and share machine learning apps, all in Python. ### Geolocation _Libraries for geocoding addresses and working with latitudes and longitudes._ -- [geojson](https://github.com/jazzband/geojson) - Python bindings and utilities for GeoJSON. - [geopandas](https://github.com/geopandas/geopandas) - Python tools for geographic data (GeoSeries/GeoDataFrame) built on pandas. - [geopy](https://github.com/geopy/geopy) - Python Geocoding Toolbox. +- [geojson](https://github.com/jazzband/geojson) - Python bindings and utilities for GeoJSON. - [geodjango](https://github.com/django/django) - A world-class geographic web framework that is part of [Django](https://docs.djangoproject.com/en/dev/ref/contrib/gis/). ### Science @@ -537,9 +537,9 @@ _Libraries for geocoding addresses and working with latitudes and longitudes._ _Libraries for scientific computing. Also see [Python-for-Scientists](https://github.com/TomNicholas/Python-for-Scientists)._ - Core - - [numba](https://github.com/numba/numba) - Python JIT compiler to LLVM aimed at scientific Python. - [numpy](https://github.com/numpy/numpy) - A fundamental package for scientific computing with Python. - [scipy](https://github.com/scipy/scipy) - A Python-based ecosystem of open-source software for mathematics, science, and engineering. + - [numba](https://github.com/numba/numba) - Python JIT compiler to LLVM aimed at scientific Python. - Symbolic Mathematics - [sympy](https://github.com/sympy/sympy) - A Python library for symbolic mathematics. - Statistics @@ -551,9 +551,9 @@ _Libraries for scientific computing. Also see [Python-for-Scientists](https://gi - [astropy](https://github.com/astropy/astropy) - A community Python library for Astronomy. - [obspy](https://github.com/obspy/obspy) - A Python toolbox for seismology. - Simulation and Modeling - - [mesa](https://github.com/mesa/mesa) - An agent-based modeling framework for building, analyzing, and visualizing complex system simulations. - [pymc](https://github.com/pymc-devs/pymc) - Probabilistic programming and Bayesian modeling in Python. - [simpy](https://gitlab.com/team-simpy/simpy) - A process-based discrete-event simulation framework. + - [mesa](https://github.com/mesa/mesa) - An agent-based modeling framework for building, analyzing, and visualizing complex system simulations. - Graphs and Networks - [networkx](https://github.com/networkx/networkx) - A high-productivity software for complex networks. - Computational Geometry @@ -568,8 +568,8 @@ _Libraries for quantum computing._ - [qiskit](https://github.com/Qiskit/qiskit) - An IBM-backed quantum SDK for building, simulating, and running circuits on real quantum hardware. - [qutip](https://github.com/qutip/qutip) - Quantum Toolbox in Python. -- [cirq](https://github.com/quantumlib/Cirq) - A Google-developed framework focused on hardware-aware quantum circuit design for NISQ devices. - [pennylane](https://github.com/PennyLaneAI/pennylane) - A hybrid quantum-classical machine learning library with automatic differentiation support. +- [cirq](https://github.com/quantumlib/Cirq) - A Google-developed framework focused on hardware-aware quantum circuit design for NISQ devices. **Developer Tools** @@ -628,9 +628,9 @@ _Tools of static analysis, linters and code quality checkers. Also see [awesome- _Libraries for testing codebases and generating test data. Also see [awesome-python-testing](https://github.com/cleder/awesome-python-testing)._ - Frameworks - - [hypothesis](https://github.com/HypothesisWorks/hypothesis) - Hypothesis is an advanced Quickcheck style property based testing library. - [pytest](https://github.com/pytest-dev/pytest) - A mature full-featured Python testing tool. - [awesome-pytest](https://github.com/augustogoulart/awesome-pytest) + - [hypothesis](https://github.com/HypothesisWorks/hypothesis) - Hypothesis is an advanced Quickcheck style property based testing library. - [robotframework](https://github.com/robotframework/robotframework) - A generic test automation framework. - Test Runners - [tox](https://github.com/tox-dev/tox) - Auto builds and tests distributions in multiple Python versions @@ -643,11 +643,11 @@ _Libraries for testing codebases and generating test data. Also see [awesome-pyt - API Testing - [schemathesis](https://github.com/schemathesis/schemathesis) - A tool for automatic property-based testing of web applications built with Open API / Swagger specifications. - Mock + - [responses](https://github.com/getsentry/responses) - A utility library for mocking out the requests Python library. - [freezegun](https://github.com/spulec/freezegun) - Travel through time by mocking the datetime module. - [mock](https://docs.python.org/3/library/unittest.mock.html) - (Python standard library) A mocking and patching library. - - [responses](https://github.com/getsentry/responses) - A utility library for mocking out the requests Python library. - - [respx](https://github.com/lundberg/respx) - Mock HTTPX with awesome request patterns and response side effects. - [vcrpy](https://github.com/kevin1024/vcrpy) - Record and replay HTTP interactions on your tests. + - [respx](https://github.com/lundberg/respx) - Mock HTTPX with awesome request patterns and response side effects. - Object Factories - [factory_boy](https://github.com/FactoryBoy/factory_boy) - A test fixtures replacement for Python. - [polyfactory](https://github.com/litestar-org/polyfactory) - mock data generation library with support to classes (continuation of `pydantic-factories`) @@ -902,8 +902,8 @@ _Libraries for parsing and manipulating specific text formats._ - [pyelftools](https://github.com/eliben/pyelftools) - Parsing and analyzing ELF files and DWARF debugging information. - [tablib](https://github.com/jazzband/tablib) - A module for Tabular Datasets in XLS, CSV, JSON, YAML. - File Conversion - - [docling](https://github.com/docling-project/docling) - Library for converting documents into structured data. - [markitdown](https://github.com/microsoft/markitdown) - Python tool for converting files and office documents to Markdown. + - [docling](https://github.com/docling-project/docling) - Library for converting documents into structured data. - Excel - [openpyxl](https://openpyxl.readthedocs.io/en/stable/) - A library for reading and writing Excel 2010 xlsx/xlsm/xltx/xltm files. - [xlsxwriter](https://github.com/jmcnamara/XlsxWriter) - A Python module for creating Excel .xlsx files. @@ -912,14 +912,14 @@ _Libraries for parsing and manipulating specific text formats._ - PowerPoint - [python-pptx](https://github.com/scanny/python-pptx) - Python library for creating and updating PowerPoint (.pptx) files. - PDF - - [pdfminer.six](https://github.com/pdfminer/pdfminer.six) - Pdfminer.six is a community maintained fork of the original PDFMiner. - [pypdf](https://github.com/py-pdf/pypdf) - A library capable of splitting, merging, cropping, and transforming PDF pages. - [reportlab](https://www.reportlab.com/opensource/) - Allowing Rapid creation of rich PDF documents. + - [pdfminer.six](https://github.com/pdfminer/pdfminer.six) - Pdfminer.six is a community maintained fork of the original PDFMiner. - HTML-to-PDF - [weasyprint](https://github.com/Kozea/WeasyPrint) - A visual rendering engine for HTML and CSS that can export to PDF. - Markdown - - [markdown](https://github.com/Python-Markdown/markdown) - A Python implementation of John Gruber’s Markdown. - [markdown-it-py](https://github.com/executablebooks/markdown-it-py) - Markdown parser with 100% CommonMark support, extensions, and syntax plugins. + - [markdown](https://github.com/Python-Markdown/markdown) - A Python implementation of John Gruber’s Markdown. - [mistune](https://github.com/lepture/mistune) - Fastest and full featured pure Python parsers of Markdown. - Data Formats - [pyyaml](https://github.com/yaml/pyyaml) - YAML implementations for Python. From 59cc42e2c39165ae44b925002f552e18083abe6a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 00:38:48 +0800 Subject: [PATCH 027/168] docs: sync AGENTS.md with the shortlist reform rules AGENTS.md still carried pre-reform Key Rules (mandatory alphabetical ordering, "quality over quantity" lanes-era language, no prune-sweep commit exception, no live-verification rule). Bring it in line with CLAUDE.md and CONTRIBUTING.md: downloads-descending tier ordering, 3+2 cap, sweep-commit exception, verification rule. Also record the UV_PYTHON=3.13 workaround for Python-3.14-only machines in both files' Makefile notes, and complete CLAUDE.md's Makefile target list. Co-Authored-By: Claude --- AGENTS.md | 13 +++++++------ CLAUDE.md | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 29c863bcd4..646889dc08 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,11 +6,11 @@ An opinionated list of Python frameworks, libraries, tools, and resources. Publi ## Entry Guidelines -**Refer to [CONTRIBUTING.md](CONTRIBUTING.md)** for acceptance criteria, quality requirements, rejection rules, and entry format. Apply these rules whenever adding or removing an entry, whether reviewing a PR or committing directly. +**Refer to [CONTRIBUTING.md](CONTRIBUTING.md)** for admission rules, quality requirements, rejection rules, and entry format. Apply these rules whenever adding or removing an entry, whether reviewing a PR or committing directly. ## Structure -- **README.md**: Source of truth for catalog entries and README sponsor placements. Hierarchical categories with alphabetically ordered entries. +- **README.md**: Source of truth for catalog entries and README sponsor placements. Hierarchical categories; entries ordered per the Key Rules below. - **CONTRIBUTING.md**: Submission guidelines and review criteria. - **SPONSORSHIP.md**: Sponsor tiers, placement rules, and the editorial-independence policy. `website/templates/sponsorship.html` separately defines which sponsorship content appears on the published website page. - **website/**: Static site generator that builds awesome-python.com from README.md. @@ -19,13 +19,14 @@ An opinionated list of Python frameworks, libraries, tools, and resources. Publi - `readme_parser.py`: Markdown-to-structured-data parser. - `templates/`, `static/`: Jinja2 templates and CSS/JS assets. - `tests/`: Pytest tests for the build pipeline. -- **Makefile**: `make install`, `make build`, `make preview`, `make test`, `make lint`, `make format`, `make typecheck`, `make fetch_github_stars`. +- **Makefile**: `make install`, `make build`, `make preview`, `make test`, `make lint`, `make format`, `make typecheck`, `make fetch_github_stars`. On machines with only Python 3.14, prefix uv-based targets with `UV_PYTHON=3.13` (watchdog 6.0.0 ships no 3.14 wheel and the project sets `no-build`). - **pyproject.toml**: Uses `uv` for dependency management. Python >=3.13. ## Key Rules -- Alphabetical ordering within categories is mandatory. -- Quality over quantity. Only "awesome" projects. +- Ordering within a use case: obvious choices first, then challengers, each tier by PyPI downloads/month descending; no-signal entries last in tier, alphabetically. See CONTRIBUTING.md. +- A shortlist, not a catalog: per use case, up to 3 obvious choices plus up to 2 challengers, hard maximum 5. - One project per PR. -- One entry per commit when adding or deleting entries. Format, wording, or categorization changes across multiple entries may be bundled in a single commit. +- One entry per commit when adding or deleting entries. Exception: a prune sweep is one commit per section, its body listing each removal with its reason. Format, wording, or categorization changes across multiple entries may be bundled in a single commit. +- Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Training-data recollections alone are not evidence; verify before stating, and label anything unverifiable as a judgment call. - README.md is the source of truth for catalog entries and README sponsor placements; treat `SPONSORSHIP.md` and `website/templates/sponsorship.html` as separate sponsorship content surfaces. diff --git a/CLAUDE.md b/CLAUDE.md index da1c684b89..52b9391c3a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,7 +19,7 @@ An opinionated list of Python frameworks, libraries, tools, and resources. Publi - `readme_parser.py`: Markdown-to-structured-data parser. - `templates/`, `static/`: Jinja2 templates and CSS/JS assets. - `tests/`: Pytest tests for the build pipeline. -- **Makefile**: `make install`, `make build`, `make preview`, `make test`, `make fetch_github_stars`. +- **Makefile**: `make install`, `make build`, `make preview`, `make test`, `make lint`, `make format`, `make typecheck`, `make fetch_github_stars`. On machines with only Python 3.14, prefix uv-based targets with `UV_PYTHON=3.13` (watchdog 6.0.0 ships no 3.14 wheel and the project sets `no-build`). - **pyproject.toml**: Uses `uv` for dependency management. Python >=3.13. ## Key Rules From 83f6cebd93e1113eaf1bf1e9b26818ff1c974fa1 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 00:39:29 +0800 Subject: [PATCH 028/168] feat: add audit-the-list skill for recurring section audits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Packages the audit process proven across the shortlist-reform sweeps as a reusable skill: resolve scope from the arguments (AskUserQuestion when ambiguous or absent), fetch live evidence for every entry (BigQuery downloads, repo state, PyPI metadata), draft verdicts with restructure-before-cap and tier promotions/demotions, review through the verdict-preview page, execute one commit per section on explicit go, and record durable conclusions into CONTRIBUTING.md, CLAUDE.md, AGENTS.md, and CONTEXT.md. CONTEXT.md gains the Audit glossary term (the reform sweeps were the first Audits). Rules stay single-sourced in CONTRIBUTING.md — the skill carries process only. Co-Authored-By: Claude --- .claude/skills/audit-the-list/SKILL.md | 39 ++++++++++++++++++++++++++ CONTEXT.md | 6 ++++ 2 files changed, 45 insertions(+) create mode 100644 .claude/skills/audit-the-list/SKILL.md diff --git a/.claude/skills/audit-the-list/SKILL.md b/.claude/skills/audit-the-list/SKILL.md new file mode 100644 index 0000000000..5cbc670247 --- /dev/null +++ b/.claude/skills/audit-the-list/SKILL.md @@ -0,0 +1,39 @@ +--- +name: audit-the-list +description: Audit README.md sections against the shortlist rules — re-verify every entry's verdict with live data, promote or demote challengers, restructure oversized use cases, prune, and evaluate proposed additions. Fire when the maintainer asks to audit, sweep, prune, re-check, or maintain sections, or asks whether an entry (or a proposed one) deserves its slot. +argument-hint: [all sections or specific sections] +--- + +# Audit the list + +An Audit re-runs the admission test over live sections of README.md: every entry re-verified against current data, tiers reassessed, structure reconsidered, then the maintainer adjudicates and the result is committed. The rules live in CONTRIBUTING.md (Admission, Evidence, Entry Ordering) and CONTEXT.md (vocabulary) — this skill is the process that applies them, not a second copy of them. Entry changes land only on the maintainer's explicit go. + +## 1. Scope + +Resolve the scope from the arguments. Named sections mean exactly those, whether or not they were audited before (a re-run is how a past verdict gets rechecked). `all` is ambiguous — AskUserQuestion whether it means every section or only never-audited ones; prior audits are recorded in git history (`git log --oneline --grep="sweep\|audit"`). With no arguments, AskUserQuestion listing the never-audited Thematic Groups. Batch the work one Thematic Group per sitting. Done when the section list is settled. + +## 2. Evidence + +Fetch live evidence for every entry in scope before judging anything (CLAUDE.md verification rule): + +- **Downloads/month**: `cd website && UV_PYTHON=3.13 uv run python fetch_pypi_downloads.py --names-file --dry-run` first, then without `--dry-run`. The script's docstring carries the BigQuery cost constraints — read it before batching. `https://pypistats.org/api/packages/{name}/recent` for a handful of spot-checks, paced 8s or slower. +- **Repo state**: archived flag, last push, created date, stars, description — `gh api repos/{owner}/{repo}`, GitLab API for GitLab-hosted projects. +- **PyPI metadata** (`https://pypi.org/pypi/{name}/json`) wherever a name might not be the canonical package — ownership collisions and wrong display names surface here. + +Done when every entry in scope has downloads (or a stated no-signal reason), repo state, and a confirmed PyPI name. + +## 3. Verdicts + +Draft a verdict and reason for every entry, restructure before cap: decide Splits, mints, and re-homes first — cutting before restructuring destroys entries — then apply the cap tier by tier, including promotions and demotions between obvious choice and challenger. Ground every reason in the fetched evidence; label anything unverifiable as a judgment call. Where fresh evidence contradicts the standing verdict, say so in the reason instead of silently keeping the seed. + +## 4. Review and go + +Run the verdict-preview skill: it generates the interactive review page and defines how the maintainer's feedback JSON comes back and gets processed. Their verdicts are final. Before touching README.md, surface what the feedback implies but does not decide — cap overflows, homeless entries after a Split, tier for a tierless flip — as named assumptions or questions, then get an explicit go. + +## 5. Execute + +One commit per section: body lists each removal with its reason and downloads figure; restructures, tier moves, and reorders ride the same commit. Format-only outcomes (no removals) are a single style commit. `UV_PYTHON=3.13 make test` before every commit, `UV_PYTHON=3.13 make build` after the last one. Generic commit helpers tend to split a section audit into structural and per-subcategory commits — if that happens, squash back to one commit per section. Done when the tree is clean, tests passed before each commit, and the build count reconciles with the adjudicated changes. + +## 6. Record + +A conclusion that outlives the sitting goes into the repo before the audit ends: admission or evidence rules into CONTRIBUTING.md, repo process and environment facts into CLAUDE.md and AGENTS.md (kept in sync), vocabulary into CONTEXT.md. Done when nothing the next audit needs is stranded in conversation. diff --git a/CONTEXT.md b/CONTEXT.md index cab584e16c..8fae6cb833 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -46,3 +46,9 @@ _Avoid_: Rising Star (old lane name), Hidden Gem (old lane name — concept remo **Split**: Maintainer-only restructuring of an oversized Use Case into finer Use Cases (new Subcategories), considered before any trimming when the size reflects genuinely distinct jobs. A submitter's entry PR can never perform a Split. + +### Maintenance + +**Audit**: +The recurring maintenance pass over one or more Sections: every Entry's verdict re-verified against current evidence, Challengers promoted or demoted, oversized Use Cases Split, drops and admissions re-decided. The maintainer adjudicates through an interactive preview, and entry changes land only on their explicit go. The 2026-08 shortlist-reform sweeps were the first Audits. +_Avoid_: Sweep (reform-era name for a Section's first Audit) From 7f0e9239042518a988504077a09501790b88e88f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 00:41:57 +0800 Subject: [PATCH 029/168] refactor: rename verdict-preview skill to preview-verdicts Verb-first naming per maintainer preference. Directory, frontmatter name, and the audit-the-list reference updated together; template.html moves with the directory unchanged. Co-Authored-By: Claude --- .claude/skills/audit-the-list/SKILL.md | 2 +- .claude/skills/{verdict-preview => preview-verdicts}/SKILL.md | 2 +- .../skills/{verdict-preview => preview-verdicts}/template.html | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename .claude/skills/{verdict-preview => preview-verdicts}/SKILL.md (99%) rename .claude/skills/{verdict-preview => preview-verdicts}/template.html (100%) diff --git a/.claude/skills/audit-the-list/SKILL.md b/.claude/skills/audit-the-list/SKILL.md index 5cbc670247..a66851bbab 100644 --- a/.claude/skills/audit-the-list/SKILL.md +++ b/.claude/skills/audit-the-list/SKILL.md @@ -28,7 +28,7 @@ Draft a verdict and reason for every entry, restructure before cap: decide Split ## 4. Review and go -Run the verdict-preview skill: it generates the interactive review page and defines how the maintainer's feedback JSON comes back and gets processed. Their verdicts are final. Before touching README.md, surface what the feedback implies but does not decide — cap overflows, homeless entries after a Split, tier for a tierless flip — as named assumptions or questions, then get an explicit go. +Run the preview-verdicts skill: it generates the interactive review page and defines how the maintainer's feedback JSON comes back and gets processed. Their verdicts are final. Before touching README.md, surface what the feedback implies but does not decide — cap overflows, homeless entries after a Split, tier for a tierless flip — as named assumptions or questions, then get an explicit go. ## 5. Execute diff --git a/.claude/skills/verdict-preview/SKILL.md b/.claude/skills/preview-verdicts/SKILL.md similarity index 99% rename from .claude/skills/verdict-preview/SKILL.md rename to .claude/skills/preview-verdicts/SKILL.md index 1572abc589..af0de9c194 100644 --- a/.claude/skills/verdict-preview/SKILL.md +++ b/.claude/skills/preview-verdicts/SKILL.md @@ -1,5 +1,5 @@ --- -name: verdict-preview +name: preview-verdicts description: Generate the interactive keep/drop verdict preview (HTML page with per-row feedback controls) whenever a prune sweep, batch entry edit, or restructure needs maintainer review before touching README.md — and process the feedback JSON the maintainer pastes back. --- diff --git a/.claude/skills/verdict-preview/template.html b/.claude/skills/preview-verdicts/template.html similarity index 100% rename from .claude/skills/verdict-preview/template.html rename to .claude/skills/preview-verdicts/template.html From a1ed550c2dba6d0dda473c127936d9266c5e8003 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:16:21 +0800 Subject: [PATCH 030/168] fix: filter BigQuery PyPI download query on project, not file.project Live bq show verified the pypi.file_downloads table clusters on the top-level project column, not file.project as the docstring claimed. Filtering on project (values verified identical to file.project across 408M rows, zero mismatches) gets cluster pruning and cuts the full-README scan estimate from >1.2TB to ~275GB upper bound, with actual billed bytes lower still (33.7GB measured for a single name) - so full sweeps now fit the 1 TiB/month free tier. Also adds --maximum_bytes_billed=400GB as a safety cap, enforced by BigQuery pre-run against the dry-run upper-bound estimate. Co-Authored-By: Claude --- website/fetch_pypi_downloads.py | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/website/fetch_pypi_downloads.py b/website/fetch_pypi_downloads.py index e79c3620ea..ca8923c21c 100644 --- a/website/fetch_pypi_downloads.py +++ b/website/fetch_pypi_downloads.py @@ -2,13 +2,21 @@ """Fetch last-30-day PyPI download counts for README entries via BigQuery. Shells out to the `bq` CLI (Google Cloud SDK) against the public -`bigquery-public-data.pypi.file_downloads` table. The table is clustered on -file.project, so scanned bytes grow with the IN-list: a few dozen names -prune to tens of GB while the full README (~530 names) balloons to over -1 TB — past the free tier. Fetch per curation sitting with --names-file -instead of all at once. Results are cached to data/pypi_downloads.tsv -(merged with any existing rows); names with no PyPI rows are written as -NOT_FOUND. Always --dry-run first to check the scan estimate. +`bigquery-public-data.pypi.file_downloads` table. The table is partitioned +on timestamp and clustered on the top-level `project` column — filter on +`project`, never `file.project`: both hold identical values (verified +2026-08-16, 408M rows on one day, zero mismatches), but only a `project` +filter gets cluster pruning, and the `file` record costs ~4x more to scan. +A 30-day query dry-runs at up to ~275 GB (the pre-pruning upper bound for +a full-README IN list; small lists estimate lower); actual billed bytes +shrink further with cluster pruning (33.7 GB measured for a single name), +so even a full-README sweep fits the 1 TiB/month free tier. +MAX_BYTES_BILLED is a safety net against accidentally unpartitioned +queries; BigQuery enforces it against the pre-run upper bound, so it must +stay above the dry-run estimate or every query fails. Results are cached +to data/pypi_downloads.tsv (merged with any existing rows); names with no +PyPI rows are written as NOT_FOUND. Always --dry-run first to check the +scan estimate. Usage: python fetch_pypi_downloads.py [--dry-run] [--names-file FILE] """ @@ -24,6 +32,7 @@ DATA_DIR = Path(__file__).parent / "data" OUT_FILE = DATA_DIR / "pypi_downloads.tsv" README_PATH = Path(__file__).parent.parent / "README.md" +MAX_BYTES_BILLED = 400_000_000_000 # PyPI normalizes names to lowercase with runs of -, _, . collapsed to -. PYPI_NAME_RE = re.compile(r"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$") @@ -47,14 +56,14 @@ def collect_names(readme_text: str) -> list[str]: def fetch(names: list[str], dry_run: bool) -> dict[str, int]: in_list = ", ".join(f"'{name}'" for name in names) query = ( - "SELECT file.project AS project, COUNT(*) AS downloads " + "SELECT project, COUNT(*) AS downloads " "FROM `bigquery-public-data.pypi.file_downloads` " "WHERE DATE(timestamp) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) " "AND CURRENT_DATE() " - f"AND file.project IN ({in_list}) " - "GROUP BY file.project" + f"AND project IN ({in_list}) " + "GROUP BY project" ) - cmd = ["bq", "query", "--use_legacy_sql=false", "--format=json"] + cmd = ["bq", "query", "--use_legacy_sql=false", "--format=json", f"--maximum_bytes_billed={MAX_BYTES_BILLED}"] if dry_run: cmd.append("--dry_run") cmd.append(query) From fd79813ddefd5f74ecbf8a4d12cc878f0ec13b96 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:17:59 +0800 Subject: [PATCH 031/168] feat: switch default PyPI download source to ClickPy BigQuery required a personal Google Cloud account, so only the maintainer could run it and overruns cost real money. ClickPy is ClickHouse's free, keyless public mirror of the same PyPI download dataset, so it becomes the default source with a single batched query covering the full README in under a second. BigQuery stays available behind a new --bigquery flag as the canonical-source cross-check; --dry-run now only applies to that path. Live-tested: ClickPy full path (2/2 names), the --dry-run guard, and the BigQuery dry-run. Co-Authored-By: Claude --- website/fetch_pypi_downloads.py | 75 +++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/website/fetch_pypi_downloads.py b/website/fetch_pypi_downloads.py index ca8923c21c..80f9528b44 100644 --- a/website/fetch_pypi_downloads.py +++ b/website/fetch_pypi_downloads.py @@ -1,24 +1,36 @@ #!/usr/bin/env python3 -"""Fetch last-30-day PyPI download counts for README entries via BigQuery. - -Shells out to the `bq` CLI (Google Cloud SDK) against the public -`bigquery-public-data.pypi.file_downloads` table. The table is partitioned -on timestamp and clustered on the top-level `project` column — filter on -`project`, never `file.project`: both hold identical values (verified -2026-08-16, 408M rows on one day, zero mismatches), but only a `project` -filter gets cluster pruning, and the `file` record costs ~4x more to scan. -A 30-day query dry-runs at up to ~275 GB (the pre-pruning upper bound for -a full-README IN list; small lists estimate lower); actual billed bytes -shrink further with cluster pruning (33.7 GB measured for a single name), -so even a full-README sweep fits the 1 TiB/month free tier. -MAX_BYTES_BILLED is a safety net against accidentally unpartitioned -queries; BigQuery enforces it against the pre-run upper bound, so it must -stay above the dry-run estimate or every query fails. Results are cached -to data/pypi_downloads.tsv (merged with any existing rows); names with no -PyPI rows are written as NOT_FOUND. Always --dry-run first to check the -scan estimate. - -Usage: python fetch_pypi_downloads.py [--dry-run] [--names-file FILE] +"""Fetch last-30-day PyPI download counts for README entries. + +Default source is ClickPy, ClickHouse's public mirror of the PyPI download +dataset (sql-clickhouse.clickhouse.com, user `demo`, no key, no personal +account): one batched query covers the full README in under a second. +Playground limits — 60 queries/hour/IP, 1000 result rows — sit far above +a full-README sweep. The per-day table is a SummingMergeTree, so the +query must sum(count) GROUP BY, never count raw rows. Counts include +mirror/CI traffic, same as BigQuery's; never mix these figures with +pypistats.org, which excludes mirrors by default. + +--bigquery switches to the canonical source ClickPy mirrors: +`bigquery-public-data.pypi.file_downloads` via the `bq` CLI (needs a +personal GCP account, so it is a maintainer-local cross-check, not the +default). The table is partitioned on timestamp and clustered on the +top-level `project` column — filter on `project`, never `file.project`: +both hold identical values (verified 2026-08-16, 408M rows on one day, +zero mismatches), but only a `project` filter gets cluster pruning, and +the `file` record costs ~4x more to scan. A 30-day query dry-runs at up +to ~275 GB (the pre-pruning upper bound for a full-README IN list; small +lists estimate lower); actual billed bytes shrink further with cluster +pruning (33.7 GB measured for a single name), so even a full-README sweep +fits the 1 TiB/month free tier. MAX_BYTES_BILLED is a safety net against +accidentally unpartitioned queries; BigQuery enforces it against the +pre-run upper bound, so it must stay above the dry-run estimate or every +query fails. --dry-run (BigQuery only) prints the scan estimate without +running. + +Results are cached to data/pypi_downloads.tsv (merged with any existing +rows); names with no PyPI rows are written as NOT_FOUND. + +Usage: python fetch_pypi_downloads.py [--bigquery] [--dry-run] [--names-file FILE] """ import re @@ -27,12 +39,14 @@ from json import loads from pathlib import Path +import httpx from readme_parser import parse_readme DATA_DIR = Path(__file__).parent / "data" OUT_FILE = DATA_DIR / "pypi_downloads.tsv" README_PATH = Path(__file__).parent.parent / "README.md" MAX_BYTES_BILLED = 400_000_000_000 +CLICKPY_URL = "https://sql-clickhouse.clickhouse.com/?user=demo" # PyPI normalizes names to lowercase with runs of -, _, . collapsed to -. PYPI_NAME_RE = re.compile(r"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$") @@ -53,7 +67,20 @@ def collect_names(readme_text: str) -> list[str]: return sorted(names) -def fetch(names: list[str], dry_run: bool) -> dict[str, int]: +def fetch_clickpy(names: list[str]) -> dict[str, int]: + in_list = ", ".join(f"'{name}'" for name in names) + query = ( + "SELECT project, sum(count) AS downloads " + "FROM pypi.pypi_downloads_per_day " + f"WHERE project IN ({in_list}) AND date >= today() - 30 " + "GROUP BY project FORMAT JSON" + ) + resp = httpx.post(CLICKPY_URL, content=query, timeout=60) + resp.raise_for_status() + return {row["project"]: int(row["downloads"]) for row in resp.json()["data"]} + + +def fetch_bigquery(names: list[str], dry_run: bool) -> dict[str, int]: in_list = ", ".join(f"'{name}'" for name in names) query = ( "SELECT project, COUNT(*) AS downloads " @@ -80,13 +107,17 @@ def fetch(names: list[str], dry_run: bool) -> dict[str, int]: def main() -> None: dry_run = "--dry-run" in sys.argv + use_bigquery = "--bigquery" in sys.argv + if dry_run and not use_bigquery: + print("Error: --dry-run only applies to --bigquery.", file=sys.stderr) + sys.exit(1) if "--names-file" in sys.argv: names_path = Path(sys.argv[sys.argv.index("--names-file") + 1]) names = sorted({normalize(line) for line in names_path.read_text().split() if line}) else: names = collect_names(README_PATH.read_text()) print(f"Querying {len(names)} package names...") - counts = fetch(names, dry_run) + counts = fetch_bigquery(names, dry_run) if use_bigquery else fetch_clickpy(names) merged: dict[str, str] = {} if OUT_FILE.exists(): for line in OUT_FILE.read_text().splitlines(): From fcac01955c981a0d047315f7d2e381872d952a01 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:19:47 +0800 Subject: [PATCH 032/168] feat: add pepy.tech spot-check helper for download audits Maintainer registered a free pepy API key (PEPY_TECH_API_KEY in the gitignored repo-root .env). fetch_pepy_downloads.py sums the most recent 30 days from the v2 per-day data, throttled to the free tier's 5 requests/minute, and prints TSV without touching the single-source cache file. The audit-the-list skill's downloads bullet is rewritten in the same commit because the ClickPy-default change made its old --dry-run-first instruction fail; it now documents all three sources (ClickPy, BigQuery, pepy/pypistats) and the never-mix-mirror-counting rule. Co-Authored-By: Claude --- .claude/skills/audit-the-list/SKILL.md | 2 +- website/fetch_pepy_downloads.py | 68 ++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 website/fetch_pepy_downloads.py diff --git a/.claude/skills/audit-the-list/SKILL.md b/.claude/skills/audit-the-list/SKILL.md index a66851bbab..c87cd05fac 100644 --- a/.claude/skills/audit-the-list/SKILL.md +++ b/.claude/skills/audit-the-list/SKILL.md @@ -16,7 +16,7 @@ Resolve the scope from the arguments. Named sections mean exactly those, whether Fetch live evidence for every entry in scope before judging anything (CLAUDE.md verification rule): -- **Downloads/month**: `cd website && UV_PYTHON=3.13 uv run python fetch_pypi_downloads.py --names-file --dry-run` first, then without `--dry-run`. The script's docstring carries the BigQuery cost constraints — read it before batching. `https://pypistats.org/api/packages/{name}/recent` for a handful of spot-checks, paced 8s or slower. +- **Downloads/month**: `cd website && UV_PYTHON=3.13 uv run python fetch_pypi_downloads.py --names-file ` — default source is ClickPy (free, keyless, one batched query covers the full README). `--bigquery` switches to the canonical cross-check on the maintainer's own GCP account; there, run `--dry-run` first and read the docstring's cost constraints before batching. Spot-checks: `uv run python fetch_pepy_downloads.py ...` (needs `PEPY_TECH_API_KEY` in repo-root `.env`, throttled to 5 requests/minute) or `https://pypistats.org/api/packages/{name}/recent` paced 8s or slower. pypistats excludes mirror/CI traffic; ClickPy, BigQuery, and pepy include it — never mix sources within one comparison. - **Repo state**: archived flag, last push, created date, stars, description — `gh api repos/{owner}/{repo}`, GitLab API for GitLab-hosted projects. - **PyPI metadata** (`https://pypi.org/pypi/{name}/json`) wherever a name might not be the canonical package — ownership collisions and wrong display names surface here. diff --git a/website/fetch_pepy_downloads.py b/website/fetch_pepy_downloads.py new file mode 100644 index 0000000000..cd763f6c17 --- /dev/null +++ b/website/fetch_pepy_downloads.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +"""Spot-check last-30-day PyPI download counts via the pepy.tech API. + +Cross-check for a handful of packages during audits — not for full-README +sweeps: the free API key is throttled to 5 requests/minute (10 burst), so +this script sleeps 12s between requests and 530 names would take ~2 hours +(use fetch_pypi_downloads.py for bulk). Reads PEPY_TECH_API_KEY from the +environment, falling back to the repo-root .env. The v2 endpoint returns +~90 days of per-day per-version counts; this script sums the most recent +30 days present in the response across all versions. pepy counts include +mirror/CI traffic (CI filtering is a paid pepy feature), matching the +ClickPy/BigQuery figures; pypistats.org excludes mirrors, so never mix +the two in one comparison. Results print to stdout as TSV and are not +cached — data/pypi_downloads.tsv stays single-source. + +Usage: python fetch_pepy_downloads.py NAME [NAME ...] +""" + +import os +import sys +import time +from pathlib import Path + +import httpx +from fetch_pypi_downloads import normalize + +ENV_FILE = Path(__file__).parent.parent / ".env" +PEPY_URL = "https://api.pepy.tech/api/v2/projects/{name}" +SECONDS_BETWEEN_REQUESTS = 12 + + +def load_api_key() -> str: + key = os.environ.get("PEPY_TECH_API_KEY", "") + if not key and ENV_FILE.exists(): + for line in ENV_FILE.read_text().splitlines(): + name, sep, value = line.partition("=") + if sep and name.strip() == "PEPY_TECH_API_KEY": + key = value.strip() + if not key: + print("Error: PEPY_TECH_API_KEY not set (environment or repo-root .env).", file=sys.stderr) + sys.exit(1) + return key + + +def last_30_day_total(downloads_per_day: dict[str, dict[str, int]]) -> int: + recent_days = sorted(downloads_per_day)[-30:] + return sum(sum(downloads_per_day[day].values()) for day in recent_days) + + +def main() -> None: + if len(sys.argv) < 2: + print("Usage: python fetch_pepy_downloads.py NAME [NAME ...]", file=sys.stderr) + sys.exit(1) + names = [normalize(name) for name in sys.argv[1:]] + with httpx.Client(headers={"X-API-Key": load_api_key()}, timeout=30) as client: + for i, name in enumerate(names): + if i: + time.sleep(SECONDS_BETWEEN_REQUESTS) + resp = client.get(PEPY_URL.format(name=name)) + if resp.status_code == 404: + print(f"{name}\tNOT_FOUND") + continue + resp.raise_for_status() + print(f"{name}\t{last_30_day_total(resp.json()['downloads'])}") + + +if __name__ == "__main__": + main() From f39d00da3112d1227cfc0fbadeedc6cf5c1dd56c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:32:28 +0800 Subject: [PATCH 033/168] audit: sweep Web Frameworks to the shortlist cap First Audit of the section; maintainer adjudicated 2026-08-16 at the preview review, flipping pyramid to keep (enters as Synchronous Challenger beside fasthtml; the three Obvious slots stay flask, django, bottle). Both tiers reordered by downloads/month per the ordering rule. Removed (downloads are PyPI last-30-day via BigQuery, fetched 2026-08-16): - masonite (26.4K/month): no adoption; Laravel-style niche - microdot (10.4K/month): MicroPython-targeted, genuinely small audience - robyn (50.9K/month): installs never followed the buzz Co-Authored-By: Claude --- README.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0857aed49e..0d5a8d8dcf 100644 --- a/README.md +++ b/README.md @@ -236,23 +236,20 @@ _Libraries for building recommender systems._ _Traditional full stack web frameworks. Also see [Web APIs](#web-apis)._ - Synchronous - - [bottle](https://github.com/bottlepy/bottle) - A fast and simple micro-framework distributed as a single file with no dependencies. - - [django](https://github.com/django/django) - The most popular web framework in Python. - - [awesome-django](https://github.com/wsvincent/awesome-django) - [flask](https://github.com/pallets/flask) - A microframework for Python. - [awesome-flask](https://github.com/humiaozuzu/awesome-flask) + - [django](https://github.com/django/django) - The most popular web framework in Python. + - [awesome-django](https://github.com/wsvincent/awesome-django) + - [bottle](https://github.com/bottlepy/bottle) - A fast and simple micro-framework distributed as a single file with no dependencies. - [pyramid](https://github.com/Pylons/pyramid) - A small, fast, down-to-earth, open source Python web framework. - [awesome-pyramid](https://github.com/uralbash/awesome-pyramid) - [fasthtml](https://github.com/AnswerDotAI/fasthtml) - The fastest way to create an HTML app. - [awesome-fasthtml](https://github.com/amosgyamfi/awesome-fasthtml) - - [masonite](https://github.com/MasoniteFramework/masonite) - The modern and developer centric Python web framework. - Asynchronous - - [litestar](https://github.com/litestar-org/litestar) - Production-ready, capable and extensible ASGI Web framework. - - [microdot](https://github.com/miguelgrinberg/microdot) - The impossibly small web framework for Python and MicroPython. - - [reflex](https://github.com/reflex-dev/reflex) - A framework for building reactive, full-stack web applications entirely with Python. - - [robyn](https://github.com/sparckles/Robyn) - A high-performance async Python web framework with a Rust runtime. - [starlette](https://github.com/Kludex/starlette) - A lightweight ASGI framework and toolkit for building high-performance async services. - [tornado](https://github.com/tornadoweb/tornado) - A web framework and asynchronous networking library. + - [litestar](https://github.com/litestar-org/litestar) - Production-ready, capable and extensible ASGI Web framework. + - [reflex](https://github.com/reflex-dev/reflex) - A framework for building reactive, full-stack web applications entirely with Python. ### Web APIs From b26c30d4a929b280648320472fa0a48249e3f28c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:32:49 +0800 Subject: [PATCH 034/168] audit: sweep Web APIs to the shortlist cap First Audit of the section; maintainer adjudicated 2026-08-16 at the preview review, flipping django-modern-rest to keep (enters as the Django Challenger; Obvious slots stay django-rest-framework, django-ninja, strawberry-django). Tiers reordered by downloads/month. Removed (downloads are PyPI last-30-day via BigQuery, fetched 2026-08-16): - falcon (1.8M/month): active, but not named unprompted since fastapi/litestar; judgment call - sanic (1.8M/month): same judgment as falcon - declining mindshare, successor to nothing - webargs (3.8M/month): request-parsing helper, not an API framework; wrong job for the section Co-Authored-By: Claude --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0d5a8d8dcf..cf583afda8 100644 --- a/README.md +++ b/README.md @@ -256,19 +256,16 @@ _Traditional full stack web frameworks. Also see [Web APIs](#web-apis)._ _Libraries for building RESTful and GraphQL APIs._ - Django - - [django-modern-rest](https://github.com/wemake-services/django-modern-rest) - Modern REST with speed, types, async, `msgspec`, `pydantic` and other goodies! - - [django-ninja](https://github.com/vitalik/django-ninja) - Fast, Django REST framework based on type hints and Pydantic. - [django-rest-framework](https://github.com/encode/django-rest-framework) - A powerful and flexible toolkit to build web APIs. + - [django-ninja](https://github.com/vitalik/django-ninja) - Fast, Django REST framework based on type hints and Pydantic. - [strawberry-django](https://github.com/strawberry-graphql/strawberry-django) - Strawberry GraphQL integration with Django. + - [django-modern-rest](https://github.com/wemake-services/django-modern-rest) - Modern REST with speed, types, async, `msgspec`, `pydantic` and other goodies! - Flask - [apiflask](https://github.com/apiflask/apiflask) - A lightweight Python web API framework based on Flask and Marshmallow. - Framework Agnostic - - [connexion](https://github.com/spec-first/connexion) - A spec-first framework that automatically handles requests based on your OpenAPI specification. - - [falcon](https://github.com/falconry/falcon) - A high-performance framework for building cloud APIs and web app backends. - [fastapi](https://github.com/fastapi/fastapi) - A modern, fast, web framework for building APIs with standard Python type hints. - - [sanic](https://github.com/sanic-org/sanic) - A Python web server and web framework that's written to go fast. + - [connexion](https://github.com/spec-first/connexion) - A spec-first framework that automatically handles requests based on your OpenAPI specification. - [strawberry](https://github.com/strawberry-graphql/strawberry) - A GraphQL library that leverages Python type annotations for schema definition. - - [webargs](https://github.com/marshmallow-code/webargs) - A friendly library for parsing HTTP request arguments with built-in support for popular web frameworks. ### Web Servers From fb35807e8342bad8a92b49d7aa62b9d22359a659 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:33:18 +0800 Subject: [PATCH 035/168] audit: sweep Web Servers to the shortlist cap First Audit of the section. Restructure first: the RPC Subcategory is not an "ASGI and WSGI compatible web server" - it moves to Web APIs, whose description gains RPC; grpcio rides the move. ASGI reordered by downloads/month (uvicorn Obvious; granian, hypercorn Challengers - hypercorn kept with a watch, repo quiet since 2025-11). Maintainer-adjudicated 2026-08-16. Removed (downloads are PyPI last-30-day via BigQuery, fetched 2026-08-16): - daphne (6.5M/month): installed as Django Channels' dependency, not chosen standalone; judgment call - uwsgi (2.0M/month): officially in maintenance mode; repo quiet since 2025-10 - rpyc (1.6M/month): repo last push 2025-08-14, exactly 12 months - at the abandonment line Co-Authored-By: Claude --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index cf583afda8..59ca7f6a71 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ _Traditional full stack web frameworks. Also see [Web APIs](#web-apis)._ ### Web APIs -_Libraries for building RESTful and GraphQL APIs._ +_Libraries for building RESTful, GraphQL, and RPC APIs._ - Django - [django-rest-framework](https://github.com/encode/django-rest-framework) - A powerful and flexible toolkit to build web APIs. @@ -266,23 +266,20 @@ _Libraries for building RESTful and GraphQL APIs._ - [fastapi](https://github.com/fastapi/fastapi) - A modern, fast, web framework for building APIs with standard Python type hints. - [connexion](https://github.com/spec-first/connexion) - A spec-first framework that automatically handles requests based on your OpenAPI specification. - [strawberry](https://github.com/strawberry-graphql/strawberry) - A GraphQL library that leverages Python type annotations for schema definition. +- RPC + - [grpcio](https://github.com/grpc/grpc) - HTTP/2-based RPC framework with Python bindings, built by Google. ### Web Servers _ASGI and WSGI compatible web servers._ - ASGI - - [daphne](https://github.com/django/daphne) - An HTTP, HTTP/2 and WebSocket protocol server for ASGI and ASGI-HTTP. + - [uvicorn](https://github.com/Kludex/uvicorn) - A lightning-fast ASGI server implementation, using uvloop and httptools. - [granian](https://github.com/emmett-framework/granian) - A Rust HTTP server for Python applications built on top of Hyper and Tokio, supporting WSGI/ASGI/RSGI. - [hypercorn](https://github.com/pgjones/hypercorn) - An ASGI and WSGI Server based on Hyper libraries and inspired by Gunicorn. - - [uvicorn](https://github.com/Kludex/uvicorn) - A lightning-fast ASGI server implementation, using uvloop and httptools. - WSGI - [gunicorn](https://github.com/benoitc/gunicorn) - Pre-forked, ported from Ruby's Unicorn project. - - [uwsgi](https://github.com/unbit/uwsgi) - A project aims at developing a full stack for building hosting services, written in C. - [waitress](https://github.com/Pylons/waitress) - Multi-threaded, powers Pyramid. -- RPC - - [grpcio](https://github.com/grpc/grpc) - HTTP/2-based RPC framework with Python bindings, built by Google. - - [rpyc](https://github.com/tomerfiliba-org/rpyc) (Remote Python Call) - A transparent and symmetric RPC library for Python. ### WebSocket From 69e03b7e47da5291245f1428303dd4694a3a2125 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:33:33 +0800 Subject: [PATCH 036/168] audit: sweep WebSocket to the shortlist cap First Audit of the section; maintainer adjudicated 2026-08-16 at the preview review, flipping autobahn-python to keep (enters as the Challenger; Obvious slots are websockets, channels, flask-socketio). Reordered by downloads/month within tiers. Removed (downloads are PyPI last-30-day via BigQuery, fetched 2026-08-16): - picows (66.3K/month): 290 stars; Challenger bar (adoption trajectory) not met Co-Authored-By: Claude --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 59ca7f6a71..6012e1b0dc 100644 --- a/README.md +++ b/README.md @@ -285,11 +285,10 @@ _ASGI and WSGI compatible web servers._ _Libraries for working with WebSocket._ -- [autobahn-python](https://github.com/crossbario/autobahn-python) - WebSocket & WAMP for Python on Twisted and [asyncio](https://docs.python.org/3/library/asyncio.html). +- [websockets](https://github.com/python-websockets/websockets) - A library for building WebSocket servers and clients with a focus on correctness and simplicity. - [channels](https://github.com/django/channels) - Developer-friendly asynchrony for Django. - [flask-socketio](https://github.com/miguelgrinberg/Flask-SocketIO) - Socket.IO integration for Flask applications. -- [picows](https://github.com/tarasko/picows) - Fastest WebSocket clients and servers with a frame level interface for the most demanding use-cases. -- [websockets](https://github.com/python-websockets/websockets) - A library for building WebSocket servers and clients with a focus on correctness and simplicity. +- [autobahn-python](https://github.com/crossbario/autobahn-python) - WebSocket & WAMP for Python on Twisted and [asyncio](https://docs.python.org/3/library/asyncio.html). ### Template Engines From 6b9a1cca57ec604b6ef45800fdcaae531d9feb48 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:33:54 +0800 Subject: [PATCH 037/168] audit: sweep Admin Panels to the shortlist cap First Audit of the section (flat Section = one Use Case, 7 entries over the cap). Restructure first: flower is the Celery monitoring dashboard, not an admin-panel library - it re-homes to Task Queues as a sub-item under celery (outside the cap, aws-sdk-pandas precedent; Task Queues sits at the hard max 5). Kept: flask-admin, django-unfold (Obvious), django-grappelli (Challenger), ordered by downloads/month. Maintainer-adjudicated 2026-08-16. Removed (downloads are PyPI last-30-day via BigQuery, fetched 2026-08-16): - ajenti (4.5K/month; its ajenti-panel package adds 4.5K): Linux server control panel application, not a Python admin library - func-to-web (3.5K/month): repo created 2025-10, 425 stars; no adoption - jet-bridge (3.7K/month): bridge into the Jet Admin SaaS, not a library readers seek here Co-Authored-By: Claude --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6012e1b0dc..381b09674b 100644 --- a/README.md +++ b/README.md @@ -323,13 +323,9 @@ _Libraries for implementing authentication schemes._ _Libraries for administrative interfaces._ -- [ajenti](https://github.com/ajenti/ajenti) - The admin panel your servers deserve. -- [django-grappelli](https://github.com/sehmaschine/django-grappelli) - A jazzy skin for the Django Admin-Interface. -- [django-unfold](https://github.com/unfoldadmin/django-unfold) - Elevate your Django admin with a stunning modern interface, powerful features, and seamless user experience. - [flask-admin](https://github.com/pallets-eco/flask-admin) - Simple and extensible administrative interface framework for Flask. -- [flower](https://github.com/mher/flower) - Real-time monitor and web admin for Celery. -- [func-to-web](https://github.com/offerrall/FuncToWeb) - Instantly create web UIs from Python functions using type hints. Zero frontend code required. -- [jet-bridge](https://github.com/jet-admin/jet-bridge) - Admin panel framework for any application with nice UI (ex Jet Django). +- [django-unfold](https://github.com/unfoldadmin/django-unfold) - Elevate your Django admin with a stunning modern interface, powerful features, and seamless user experience. +- [django-grappelli](https://github.com/sehmaschine/django-grappelli) - A jazzy skin for the Django Admin-Interface. ### CMS @@ -733,6 +729,7 @@ _Frameworks and libraries for Distributed Computing._ _Libraries for working with task queues._ - [celery](https://github.com/celery/celery) - An asynchronous task queue/job queue based on distributed message passing. + - [flower](https://github.com/mher/flower) - [dramatiq](https://github.com/Bogdanp/dramatiq) - A fast and reliable background task processing library for Python 3. - [huey](https://github.com/coleifer/huey) - Little multi-threaded task queue. - [rq](https://github.com/rq/rq) - Simple job queues for Python. From 4c57da829db2ce819505ca771bdd1144c8c11fed Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:34:07 +0800 Subject: [PATCH 038/168] audit: sweep CMS to the shortlist cap First Audit of the section; maintainer adjudicated 2026-08-16. Reordered by downloads/month (wagtail, django-cms). Removed (downloads are PyPI last-30-day via BigQuery, fetched 2026-08-16): - indico (3.2K/month): event-management application (CERN), not a CMS library; readers under CMS want wagtail/django-cms - judgment call Co-Authored-By: Claude --- README.md | 3 +-- ...h_pypi_downloads.py => fetch_pypi_downloads_via_clickpy.py} | 0 ...etch_pepy_downloads.py => fetch_pypi_downloads_via_pepy.py} | 0 3 files changed, 1 insertion(+), 2 deletions(-) rename website/{fetch_pypi_downloads.py => fetch_pypi_downloads_via_clickpy.py} (100%) rename website/{fetch_pepy_downloads.py => fetch_pypi_downloads_via_pepy.py} (100%) diff --git a/README.md b/README.md index 381b09674b..08bd8b96c6 100644 --- a/README.md +++ b/README.md @@ -331,9 +331,8 @@ _Libraries for administrative interfaces._ _Content Management Systems._ -- [django-cms](https://github.com/django-cms/django-cms) - The easy-to-use and developer-friendly enterprise CMS powered by Django. -- [indico](https://github.com/indico/indico) - A feature-rich event management system, made @ [CERN](https://en.wikipedia.org/wiki/CERN). - [wagtail](https://github.com/wagtail/wagtail) - A Django content management system. +- [django-cms](https://github.com/django-cms/django-cms) - The easy-to-use and developer-friendly enterprise CMS powered by Django. ### Static Site Generators diff --git a/website/fetch_pypi_downloads.py b/website/fetch_pypi_downloads_via_clickpy.py similarity index 100% rename from website/fetch_pypi_downloads.py rename to website/fetch_pypi_downloads_via_clickpy.py diff --git a/website/fetch_pepy_downloads.py b/website/fetch_pypi_downloads_via_pepy.py similarity index 100% rename from website/fetch_pepy_downloads.py rename to website/fetch_pypi_downloads_via_pepy.py From e18d52155e7048c48cfb332546ca5234c60516d6 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:34:20 +0800 Subject: [PATCH 039/168] audit: sweep Static Site Generators to the shortlist cap First Audit of the section; maintainer adjudicated 2026-08-16. Reordered by downloads/month (pelican, nikola). Removed (downloads are PyPI last-30-day via BigQuery, fetched 2026-08-16): - lektor (12.5K/month): maintained (pushed 2026-08) but never named unprompted; close call vs nikola - judgment call Co-Authored-By: Claude --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 08bd8b96c6..caad921041 100644 --- a/README.md +++ b/README.md @@ -338,9 +338,8 @@ _Content Management Systems._ _Static site generator is a software that takes some text + templates as input and produces HTML files on the output._ -- [lektor](https://github.com/lektor/lektor) - An easy to use static CMS and blog engine. -- [nikola](https://github.com/getnikola/nikola) - A static website and blog generator. - [pelican](https://github.com/getpelican/pelican) - Static site generator that supports Markdown and reST syntax. +- [nikola](https://github.com/getnikola/nikola) - A static website and blog generator. **HTTP & Scraping** From e7e17a8e9777e2c939de5a16ec3b74c1f4186bb7 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:34:41 +0800 Subject: [PATCH 040/168] style: reorder Authentication and Web Asset Management by downloads Format-only outcomes of the 2026-08-16 Web Development Audit (no removals): OAuth entries reordered by downloads/month (oauthlib, authlib, django-allauth Obvious; django-oauth-toolkit Challenger), Web Asset Management reordered (django-storages, django-compressor) and its description gains "storing" to cover django-storages' actual job. Template Engines, JWT, Permissions, WebSocket keeps already sat in rule order. Co-Authored-By: Claude --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index caad921041..623554894b 100644 --- a/README.md +++ b/README.md @@ -299,20 +299,20 @@ _Libraries and tools for templating and lexing._ ### Web Asset Management -_Tools for managing, compressing and minifying website assets._ +_Tools for managing, storing, compressing and minifying website assets._ -- [django-compressor](https://github.com/django-compressor/django-compressor) - Compresses linked and inline JavaScript or CSS into a single cached file. - [django-storages](https://github.com/jschneier/django-storages) - A collection of custom storage back ends for Django. +- [django-compressor](https://github.com/django-compressor/django-compressor) - Compresses linked and inline JavaScript or CSS into a single cached file. ### Authentication _Libraries for implementing authentication schemes._ - OAuth + - [oauthlib](https://github.com/oauthlib/oauthlib) - A generic and thorough implementation of the OAuth request-signing logic. - [authlib](https://github.com/authlib/authlib) - A comprehensive library for building OAuth, OpenID Connect, and JWT/JWS/JWE/JWK/JWA. - [django-allauth](https://github.com/pennersr/django-allauth) - Authentication app for Django that "just works." - [django-oauth-toolkit](https://github.com/django-oauth/django-oauth-toolkit) - OAuth 2 goodies for Django. - - [oauthlib](https://github.com/oauthlib/oauthlib) - A generic and thorough implementation of the OAuth request-signing logic. - JWT - [pyjwt](https://github.com/jpadilla/pyjwt) - JSON Web Token implementation in Python. - Permissions From 7447549805a0742e9ad2672ee41e96d68b15e41e Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:35:17 +0800 Subject: [PATCH 041/168] docs: define Sub-item in CONTEXT.md The device now has two precedents (aws-sdk-pandas under pandas, flower under celery in the 2026-08-16 Web Development Audit) plus the awesome-* links; future Audits need the term - an indented link that holds no slot and rides its parent outside the Cap. Co-Authored-By: Claude --- CONTEXT.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CONTEXT.md b/CONTEXT.md index 8fae6cb833..68322b70bb 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -9,6 +9,9 @@ The editorial domain of awesome-python: which projects the list carries, how the **Entry**: A single listed project: `- [name](url) - Description.` The unit that is admitted, displaced, or pruned. Named by PyPI package name when one exists, else by repository name. +**Sub-item**: +An indented link under an Entry (awesome-django under django, aws-sdk-pandas under pandas, flower under celery). Not an Entry: it holds no slot, does not count against the Cap, and rides its parent — re-homed or removed with it. Maintainer-only placement for a companion project whose job is inseparable from its parent's. + **Thematic Group**: A bold group line (e.g. "AI & ML", "Web Development") that clusters Sections in the TOC and the Projects body. From 5297061a4f23301184daa1167e43e37bd5e02ae1 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:35:24 +0800 Subject: [PATCH 042/168] refactor: rename download-fetch scripts to source-suffixed scheme fetch_pypi_downloads.py becomes fetch_pypi_downloads_via_clickpy.py and fetch_pepy_downloads.py becomes fetch_pypi_downloads_via_pepy.py, ahead of splitting the BigQuery path into its own file. Updates the usage strings, the cross-file import, and the audit-the-list skill's references to match. Pure rename, no behavior change. Co-Authored-By: Claude --- .claude/skills/audit-the-list/SKILL.md | 2 +- website/fetch_pypi_downloads_via_clickpy.py | 2 +- website/fetch_pypi_downloads_via_pepy.py | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.claude/skills/audit-the-list/SKILL.md b/.claude/skills/audit-the-list/SKILL.md index c87cd05fac..a29da0a6cd 100644 --- a/.claude/skills/audit-the-list/SKILL.md +++ b/.claude/skills/audit-the-list/SKILL.md @@ -16,7 +16,7 @@ Resolve the scope from the arguments. Named sections mean exactly those, whether Fetch live evidence for every entry in scope before judging anything (CLAUDE.md verification rule): -- **Downloads/month**: `cd website && UV_PYTHON=3.13 uv run python fetch_pypi_downloads.py --names-file ` — default source is ClickPy (free, keyless, one batched query covers the full README). `--bigquery` switches to the canonical cross-check on the maintainer's own GCP account; there, run `--dry-run` first and read the docstring's cost constraints before batching. Spot-checks: `uv run python fetch_pepy_downloads.py ...` (needs `PEPY_TECH_API_KEY` in repo-root `.env`, throttled to 5 requests/minute) or `https://pypistats.org/api/packages/{name}/recent` paced 8s or slower. pypistats excludes mirror/CI traffic; ClickPy, BigQuery, and pepy include it — never mix sources within one comparison. +- **Downloads/month**: `cd website && UV_PYTHON=3.13 uv run python fetch_pypi_downloads_via_clickpy.py --names-file ` — default source is ClickPy (free, keyless, one batched query covers the full README). `--bigquery` switches to the canonical cross-check on the maintainer's own GCP account; there, run `--dry-run` first and read the docstring's cost constraints before batching. Spot-checks: `uv run python fetch_pypi_downloads_via_pepy.py ...` (needs `PEPY_TECH_API_KEY` in repo-root `.env`, throttled to 5 requests/minute) or `https://pypistats.org/api/packages/{name}/recent` paced 8s or slower. pypistats excludes mirror/CI traffic; ClickPy, BigQuery, and pepy include it — never mix sources within one comparison. - **Repo state**: archived flag, last push, created date, stars, description — `gh api repos/{owner}/{repo}`, GitLab API for GitLab-hosted projects. - **PyPI metadata** (`https://pypi.org/pypi/{name}/json`) wherever a name might not be the canonical package — ownership collisions and wrong display names surface here. diff --git a/website/fetch_pypi_downloads_via_clickpy.py b/website/fetch_pypi_downloads_via_clickpy.py index 80f9528b44..1cae54a7e6 100644 --- a/website/fetch_pypi_downloads_via_clickpy.py +++ b/website/fetch_pypi_downloads_via_clickpy.py @@ -30,7 +30,7 @@ Results are cached to data/pypi_downloads.tsv (merged with any existing rows); names with no PyPI rows are written as NOT_FOUND. -Usage: python fetch_pypi_downloads.py [--bigquery] [--dry-run] [--names-file FILE] +Usage: python fetch_pypi_downloads_via_clickpy.py [--bigquery] [--dry-run] [--names-file FILE] """ import re diff --git a/website/fetch_pypi_downloads_via_pepy.py b/website/fetch_pypi_downloads_via_pepy.py index cd763f6c17..998f260f90 100644 --- a/website/fetch_pypi_downloads_via_pepy.py +++ b/website/fetch_pypi_downloads_via_pepy.py @@ -4,7 +4,7 @@ Cross-check for a handful of packages during audits — not for full-README sweeps: the free API key is throttled to 5 requests/minute (10 burst), so this script sleeps 12s between requests and 530 names would take ~2 hours -(use fetch_pypi_downloads.py for bulk). Reads PEPY_TECH_API_KEY from the +(use fetch_pypi_downloads_via_clickpy.py for bulk). Reads PEPY_TECH_API_KEY from the environment, falling back to the repo-root .env. The v2 endpoint returns ~90 days of per-day per-version counts; this script sums the most recent 30 days present in the response across all versions. pepy counts include @@ -13,7 +13,7 @@ the two in one comparison. Results print to stdout as TSV and are not cached — data/pypi_downloads.tsv stays single-source. -Usage: python fetch_pepy_downloads.py NAME [NAME ...] +Usage: python fetch_pypi_downloads_via_pepy.py NAME [NAME ...] """ import os @@ -22,7 +22,7 @@ from pathlib import Path import httpx -from fetch_pypi_downloads import normalize +from fetch_pypi_downloads_via_clickpy import normalize ENV_FILE = Path(__file__).parent.parent / ".env" PEPY_URL = "https://api.pepy.tech/api/v2/projects/{name}" @@ -49,7 +49,7 @@ def last_30_day_total(downloads_per_day: dict[str, dict[str, int]]) -> int: def main() -> None: if len(sys.argv) < 2: - print("Usage: python fetch_pepy_downloads.py NAME [NAME ...]", file=sys.stderr) + print("Usage: python fetch_pypi_downloads_via_pepy.py NAME [NAME ...]", file=sys.stderr) sys.exit(1) names = [normalize(name) for name in sys.argv[1:]] with httpx.Client(headers={"X-API-Key": load_api_key()}, timeout=30) as client: From 5ece46f262ad56a16ddbc457be586514cd9de867 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:39:14 +0800 Subject: [PATCH 043/168] docs: cover awesome-* links in the Sub-item definition Follow-up to d07440f: the definition's placement clause described only companion projects (flower/celery), but awesome-* also-see lists are Sub-items too. Co-Authored-By: Claude --- CONTEXT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTEXT.md b/CONTEXT.md index 68322b70bb..f4b23b2c31 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -10,7 +10,7 @@ The editorial domain of awesome-python: which projects the list carries, how the A single listed project: `- [name](url) - Description.` The unit that is admitted, displaced, or pruned. Named by PyPI package name when one exists, else by repository name. **Sub-item**: -An indented link under an Entry (awesome-django under django, aws-sdk-pandas under pandas, flower under celery). Not an Entry: it holds no slot, does not count against the Cap, and rides its parent — re-homed or removed with it. Maintainer-only placement for a companion project whose job is inseparable from its parent's. +An indented link under an Entry (awesome-django under django, aws-sdk-pandas under pandas, flower under celery). Not an Entry: it holds no slot, does not count against the Cap, and rides its parent — re-homed or removed with it. Maintainer-only placement, for a companion project whose job is inseparable from its parent's (flower monitors celery) or an awesome-* also-see list. **Thematic Group**: A bold group line (e.g. "AI & ML", "Web Development") that clusters Sections in the TOC and the Projects body. From 1abfb1af42139e2d1fc003130a36f54bd86d5c0f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:57:16 +0800 Subject: [PATCH 044/168] refactor: split download fetchers into writer and cross-check scripts Authored by the parallel fetch-scripts session (its intended 0cffb5f never landed; the content rode into an audit commit by accident and is extracted here): fetch_pypi_downloads_via_clickpy.py becomes the flagless full-README sweep and sole writer of data/pypi_downloads.tsv; new fetch_pypi_downloads_via_bigquery.py is a print-only cross-check taking explicit names behind a 400 GB billing cap; audit-the-list SKILL.md step 2 updated to match. Co-Authored-By: Claude --- .claude/skills/audit-the-list/SKILL.md | 2 +- website/fetch_pypi_downloads_via_bigquery.py | 72 +++++++++++++++ website/fetch_pypi_downloads_via_clickpy.py | 95 ++++---------------- 3 files changed, 91 insertions(+), 78 deletions(-) create mode 100644 website/fetch_pypi_downloads_via_bigquery.py diff --git a/.claude/skills/audit-the-list/SKILL.md b/.claude/skills/audit-the-list/SKILL.md index a29da0a6cd..be48f239f8 100644 --- a/.claude/skills/audit-the-list/SKILL.md +++ b/.claude/skills/audit-the-list/SKILL.md @@ -16,7 +16,7 @@ Resolve the scope from the arguments. Named sections mean exactly those, whether Fetch live evidence for every entry in scope before judging anything (CLAUDE.md verification rule): -- **Downloads/month**: `cd website && UV_PYTHON=3.13 uv run python fetch_pypi_downloads_via_clickpy.py --names-file ` — default source is ClickPy (free, keyless, one batched query covers the full README). `--bigquery` switches to the canonical cross-check on the maintainer's own GCP account; there, run `--dry-run` first and read the docstring's cost constraints before batching. Spot-checks: `uv run python fetch_pypi_downloads_via_pepy.py ...` (needs `PEPY_TECH_API_KEY` in repo-root `.env`, throttled to 5 requests/minute) or `https://pypistats.org/api/packages/{name}/recent` paced 8s or slower. pypistats excludes mirror/CI traffic; ClickPy, BigQuery, and pepy include it — never mix sources within one comparison. +- **Downloads/month**: `cd website && UV_PYTHON=3.13 uv run python fetch_pypi_downloads_via_clickpy.py` — free keyless ClickPy sweep of the full README, sole writer of `data/pypi_downloads.tsv` (rewritten from scratch each run). Cross-checks print to stdout, take explicit names, and never touch the cache: `fetch_pypi_downloads_via_bigquery.py ...` (canonical source, maintainer's own GCP account, `--dry-run` first — the docstring carries the cost constraints; full-README sweeps exceed the free tier, keep name lists small), `fetch_pypi_downloads_via_pepy.py ...` (needs `PEPY_TECH_API_KEY` in repo-root `.env`, throttled to 5 requests/minute), or `https://pypistats.org/api/packages/{name}/recent` paced 8s or slower. pypistats excludes mirror/CI traffic; ClickPy, BigQuery, and pepy include it — never mix sources within one comparison. - **Repo state**: archived flag, last push, created date, stars, description — `gh api repos/{owner}/{repo}`, GitLab API for GitLab-hosted projects. - **PyPI metadata** (`https://pypi.org/pypi/{name}/json`) wherever a name might not be the canonical package — ownership collisions and wrong display names surface here. diff --git a/website/fetch_pypi_downloads_via_bigquery.py b/website/fetch_pypi_downloads_via_bigquery.py new file mode 100644 index 0000000000..21f69479a1 --- /dev/null +++ b/website/fetch_pypi_downloads_via_bigquery.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""Cross-check last-30-day PyPI download counts for given names via BigQuery. + +Queries the canonical source ClickPy mirrors — +`bigquery-public-data.pypi.file_downloads` via the `bq` CLI — and prints +namecount TSV to stdout. Maintainer-local (needs a personal GCP +account) and print-only: data/pypi_downloads.tsv is written solely by +fetch_pypi_downloads_via_clickpy.py. + +Targeted cross-checks only — full-README sweeps belong to ClickPy. The +dry-run scan estimate scales with the IN list (measured 2026-08-16: +~38 GB for 2 names, ~275 GB for 53, ~1.2 TB for the full README — past +both MAX_BYTES_BILLED and the 1 TiB/month free tier), and BigQuery +enforces MAX_BYTES_BILLED against that pre-run estimate, so oversized +name lists fail before billing. Actual billed bytes come in far lower +via cluster pruning (33.7 GB for a single name). The table is +partitioned on timestamp and clustered on the top-level `project` +column — filter on `project`, never `file.project`: both hold identical +values (verified 2026-08-16, 408M rows on one day, zero mismatches), but +only a `project` filter gets cluster pruning, and the `file` record +costs ~4x more to scan. Always --dry-run first to check the estimate. + +Usage: python fetch_pypi_downloads_via_bigquery.py [--dry-run] NAME [NAME ...] +""" + +import subprocess +import sys +from json import loads + +from fetch_pypi_downloads_via_clickpy import normalize + +MAX_BYTES_BILLED = 400_000_000_000 + + +def fetch_bigquery(names: list[str], dry_run: bool) -> dict[str, int]: + in_list = ", ".join(f"'{name}'" for name in names) + query = ( + "SELECT project, COUNT(*) AS downloads " + "FROM `bigquery-public-data.pypi.file_downloads` " + "WHERE DATE(timestamp) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) " + "AND CURRENT_DATE() " + f"AND project IN ({in_list}) " + "GROUP BY project" + ) + cmd = ["bq", "query", "--use_legacy_sql=false", "--format=json", f"--maximum_bytes_billed={MAX_BYTES_BILLED}"] + if dry_run: + cmd.append("--dry_run") + cmd.append(query) + result = subprocess.run(cmd, capture_output=True, text=True) + if result.returncode != 0: + print(result.stderr, file=sys.stderr) + sys.exit(1) + if dry_run: + print(result.stdout.strip() or result.stderr.strip()) + sys.exit(0) + rows = loads(result.stdout) + return {row["project"]: int(row["downloads"]) for row in rows} + + +def main() -> None: + dry_run = "--dry-run" in sys.argv + names = sorted({normalize(arg) for arg in sys.argv[1:] if arg != "--dry-run"}) + if not names: + print("Usage: python fetch_pypi_downloads_via_bigquery.py [--dry-run] NAME [NAME ...]", file=sys.stderr) + sys.exit(1) + counts = fetch_bigquery(names, dry_run) + for name in names: + print(f"{name}\t{counts.get(name, 'NOT_FOUND')}") + + +if __name__ == "__main__": + main() diff --git a/website/fetch_pypi_downloads_via_clickpy.py b/website/fetch_pypi_downloads_via_clickpy.py index 1cae54a7e6..e88815acb7 100644 --- a/website/fetch_pypi_downloads_via_clickpy.py +++ b/website/fetch_pypi_downloads_via_clickpy.py @@ -1,42 +1,26 @@ #!/usr/bin/env python3 -"""Fetch last-30-day PyPI download counts for README entries. +"""Fetch last-30-day PyPI download counts for all README entries via ClickPy. -Default source is ClickPy, ClickHouse's public mirror of the PyPI download -dataset (sql-clickhouse.clickhouse.com, user `demo`, no key, no personal +ClickPy is ClickHouse's public mirror of the PyPI download dataset +(sql-clickhouse.clickhouse.com, user `demo`, no key, no personal account): one batched query covers the full README in under a second. Playground limits — 60 queries/hour/IP, 1000 result rows — sit far above a full-README sweep. The per-day table is a SummingMergeTree, so the query must sum(count) GROUP BY, never count raw rows. Counts include -mirror/CI traffic, same as BigQuery's; never mix these figures with -pypistats.org, which excludes mirrors by default. - ---bigquery switches to the canonical source ClickPy mirrors: -`bigquery-public-data.pypi.file_downloads` via the `bq` CLI (needs a -personal GCP account, so it is a maintainer-local cross-check, not the -default). The table is partitioned on timestamp and clustered on the -top-level `project` column — filter on `project`, never `file.project`: -both hold identical values (verified 2026-08-16, 408M rows on one day, -zero mismatches), but only a `project` filter gets cluster pruning, and -the `file` record costs ~4x more to scan. A 30-day query dry-runs at up -to ~275 GB (the pre-pruning upper bound for a full-README IN list; small -lists estimate lower); actual billed bytes shrink further with cluster -pruning (33.7 GB measured for a single name), so even a full-README sweep -fits the 1 TiB/month free tier. MAX_BYTES_BILLED is a safety net against -accidentally unpartitioned queries; BigQuery enforces it against the -pre-run upper bound, so it must stay above the dry-run estimate or every -query fails. --dry-run (BigQuery only) prints the scan estimate without -running. - -Results are cached to data/pypi_downloads.tsv (merged with any existing -rows); names with no PyPI rows are written as NOT_FOUND. - -Usage: python fetch_pypi_downloads_via_clickpy.py [--bigquery] [--dry-run] [--names-file FILE] +mirror/CI traffic; never mix these figures with pypistats.org, which +excludes mirrors by default. + +This script is the sole writer of data/pypi_downloads.tsv and rewrites it +from scratch each run, so entries removed from README.md drop out +naturally; names with no PyPI rows are written as NOT_FOUND. Cross-checks +against other sources (fetch_pypi_downloads_via_bigquery.py, +fetch_pypi_downloads_via_pepy.py) print to stdout and never touch the +cache. + +Usage: python fetch_pypi_downloads_via_clickpy.py """ import re -import subprocess -import sys -from json import loads from pathlib import Path import httpx @@ -45,7 +29,6 @@ DATA_DIR = Path(__file__).parent / "data" OUT_FILE = DATA_DIR / "pypi_downloads.tsv" README_PATH = Path(__file__).parent.parent / "README.md" -MAX_BYTES_BILLED = 400_000_000_000 CLICKPY_URL = "https://sql-clickhouse.clickhouse.com/?user=demo" # PyPI normalizes names to lowercase with runs of -, _, . collapsed to -. @@ -80,54 +63,12 @@ def fetch_clickpy(names: list[str]) -> dict[str, int]: return {row["project"]: int(row["downloads"]) for row in resp.json()["data"]} -def fetch_bigquery(names: list[str], dry_run: bool) -> dict[str, int]: - in_list = ", ".join(f"'{name}'" for name in names) - query = ( - "SELECT project, COUNT(*) AS downloads " - "FROM `bigquery-public-data.pypi.file_downloads` " - "WHERE DATE(timestamp) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) " - "AND CURRENT_DATE() " - f"AND project IN ({in_list}) " - "GROUP BY project" - ) - cmd = ["bq", "query", "--use_legacy_sql=false", "--format=json", f"--maximum_bytes_billed={MAX_BYTES_BILLED}"] - if dry_run: - cmd.append("--dry_run") - cmd.append(query) - result = subprocess.run(cmd, capture_output=True, text=True) - if result.returncode != 0: - print(result.stderr, file=sys.stderr) - sys.exit(1) - if dry_run: - print(result.stdout.strip() or result.stderr.strip()) - sys.exit(0) - rows = loads(result.stdout) - return {row["project"]: int(row["downloads"]) for row in rows} - - def main() -> None: - dry_run = "--dry-run" in sys.argv - use_bigquery = "--bigquery" in sys.argv - if dry_run and not use_bigquery: - print("Error: --dry-run only applies to --bigquery.", file=sys.stderr) - sys.exit(1) - if "--names-file" in sys.argv: - names_path = Path(sys.argv[sys.argv.index("--names-file") + 1]) - names = sorted({normalize(line) for line in names_path.read_text().split() if line}) - else: - names = collect_names(README_PATH.read_text()) + names = collect_names(README_PATH.read_text()) print(f"Querying {len(names)} package names...") - counts = fetch_bigquery(names, dry_run) if use_bigquery else fetch_clickpy(names) - merged: dict[str, str] = {} - if OUT_FILE.exists(): - for line in OUT_FILE.read_text().splitlines(): - name, _, value = line.partition("\t") - merged[name] = value - for name in names: - merged[name] = str(counts.get(name, "NOT_FOUND")) - OUT_FILE.write_text("\n".join(f"{name}\t{value}" for name, value in sorted(merged.items())) + "\n") - found = sum(1 for name in names if name in counts) - print(f"Done. {found}/{len(names)} names found on PyPI. Cached to {OUT_FILE}") + counts = fetch_clickpy(names) + OUT_FILE.write_text("\n".join(f"{name}\t{counts.get(name, 'NOT_FOUND')}" for name in names) + "\n") + print(f"Done. {len(counts)}/{len(names)} names found on PyPI. Cached to {OUT_FILE}") if __name__ == "__main__": From c2ba7d462c76e40ea2891a8ca0abe1d4addf6eb5 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:57:16 +0800 Subject: [PATCH 045/168] audit: sweep HTTP Clients to the shortlist cap First Audit of the section. Restructure first, maintainer-chosen at the preview review: the flat section splits into Clients and a minted URL Manipulation Subcategory holding yarl (661.9M/month via BigQuery, aio-libs, active 2026-08) and httpx.URL as a no-signal pointer to the URL class bundled with the kept httpx. Client tiers: requests, httpx, aiohttp Obvious; urllib3 in the Challenger slot by structure (transport layer under requests, count inflated by that), ordered by downloads/month. Maintainer-adjudicated 2026-08-16. Removed (downloads are PyPI last-30-day via ClickPy, fetched 2026-08-16): - furl (6.3M/month via BigQuery, same source as the yarl comparison): URL manipulation, not an HTTP client; stdlib urllib.parse covers parsing/joining/encoding and the minted Subcategory carries the ergonomic successors - yarl outpulls it 105x; repo quiet since 2026-02 - httptap (1.7K/month): CLI diagnostic tool, repo created 2025-10, 790 stars; no adoption Co-Authored-By: Claude --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 623554894b..1a1821ad4e 100644 --- a/README.md +++ b/README.md @@ -347,12 +347,14 @@ _Static site generator is a software that takes some text + templates as input a _Libraries for working with HTTP._ -- [aiohttp](https://github.com/aio-libs/aiohttp) - Asynchronous HTTP client/server framework for asyncio and Python. -- [furl](https://github.com/gruns/furl) - A small Python library that makes parsing and manipulating URLs easy. -- [httptap](https://github.com/ozeranskii/httptap) - Dissects an HTTP request into DNS, TCP, TLS, wait, and transfer phases and renders the timings as a waterfall. -- [httpx](https://github.com/encode/httpx) - A next generation HTTP client for Python. -- [requests](https://github.com/psf/requests) - HTTP Requests for Humans. -- [urllib3](https://github.com/urllib3/urllib3) - A HTTP library with thread-safe connection pooling, file post support, sanity friendly. +- General + - [requests](https://github.com/psf/requests) - HTTP Requests for Humans. + - [httpx](https://github.com/encode/httpx) - A next generation HTTP client for Python. + - [aiohttp](https://github.com/aio-libs/aiohttp) - Asynchronous HTTP client/server framework for asyncio and Python. + - [urllib3](https://github.com/urllib3/urllib3) - A HTTP library with thread-safe connection pooling, file post support, sanity friendly. +- URL Manipulation + - [yarl](https://github.com/aio-libs/yarl) - Yet another URL library. + - [httpx.URL](https://www.python-httpx.org/api/) - The immutable URL class bundled with HTTPX. ### Web Scraping From fdf66eb1f70489a131c7544d9acd37d2411bc997 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:54:20 +0800 Subject: [PATCH 046/168] audit: sweep Web Scraping to the shortlist cap First Audit of the section; maintainer adjudicated 2026-08-16. Both Subcategories reordered by downloads/month (Frameworks: browser-use, scrapy, crawl4ai; Content Extraction: feedparser, html2text with a watch - repo quiet since 2025-10 - and trafilatura). Removed (downloads are PyPI last-30-day via ClickPy, fetched 2026-08-16): - mechanicalsoup (162K/month): stateful-browsing era superseded by browser automation - crawlberg (10.6K/month): xberg-io coordinated self-promotion (the org behind the standing rejection rule); repo created 2026-03, 155 stars - website-downloader (352/month): hobby mirroring script, 174 stars - micawber (209K/month): oEmbed extraction, small audience next to the kept three - sumy (168K/month): summarization, not content extraction - wrong job for the Subcategory Co-Authored-By: Claude --- README.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/README.md b/README.md index 1a1821ad4e..2e750e484e 100644 --- a/README.md +++ b/README.md @@ -362,16 +362,11 @@ _Libraries to automate web scraping and extract web content._ - Frameworks - [browser-use](https://github.com/browser-use/browser-use) - Make websites accessible for AI agents with easy browser automation. - - [crawl4ai](https://github.com/unclecode/crawl4ai) - An open-source, LLM-friendly web crawler that provides lightning-fast, structured data extraction specifically designed for AI agents. - - [crawlberg](https://github.com/xberg-io/crawlberg) - A high-performance web crawling engine with a Rust core, headless-browser fallback, and built-in robots.txt and sitemap parsing. - - [mechanicalsoup](https://github.com/MechanicalSoup/MechanicalSoup) - A Python library for automating interaction with websites. - [scrapy](https://github.com/scrapy/scrapy) - A fast high-level screen scraping and web crawling framework. - - [website-downloader](https://github.com/PKHarsimran/website-downloader) - A modern wget --mirror / HTTrack alternative that turns whole websites into browsable offline copies. + - [crawl4ai](https://github.com/unclecode/crawl4ai) - An open-source, LLM-friendly web crawler that provides lightning-fast, structured data extraction specifically designed for AI agents. - Content Extraction - [feedparser](https://github.com/kurtmckee/feedparser) - Universal feed parser. - [html2text](https://github.com/Alir3z4/html2text) - Convert HTML to Markdown-formatted text. - - [micawber](https://github.com/coleifer/micawber) - A small library for extracting rich content from URLs. - - [sumy](https://github.com/miso-belica/sumy) - A module for automatic summarization of text documents and HTML pages. - [trafilatura](https://github.com/adbar/trafilatura) - A tool for gathering text and metadata from the web, with built-in content filtering. ### Email From d2d344fbd24578867b60bad2778896aadb6dcf60 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:54:32 +0800 Subject: [PATCH 047/168] audit: sweep Email to the shortlist cap First Audit of the section; maintainer adjudicated 2026-08-16. yagmail (346K/month, last push 2026-05) stays as the sole entry - the Cap is a ceiling, not a floor. Removed (downloads are PyPI last-30-day via ClickPy, fetched 2026-08-16): - modoboa (7.6K/month): mail-hosting platform application, not a library (ajenti/indico precedent); deployments do not flow through pip - judgment call Co-Authored-By: Claude --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 2e750e484e..9b6d8ee93e 100644 --- a/README.md +++ b/README.md @@ -373,7 +373,6 @@ _Libraries to automate web scraping and extract web content._ _Libraries for sending and parsing email, and mail server management._ -- [modoboa](https://github.com/modoboa/modoboa) - A mail hosting and management platform including a modern Web UI. - [yagmail](https://github.com/kootenpv/yagmail) - Yet another Gmail/SMTP client. **Database & Storage** From 9fc4f003fedd3b7830208c3263a144ba5a86418f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 01:55:09 +0800 Subject: [PATCH 048/168] style: rename HTTP Clients' General subcategory to Clients Maintainer follow-up to the 2026-08-16 HTTP & Scraping Audit: "HTTP Clients / General" read redundant next to URL Manipulation. Co-Authored-By: Claude --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b6d8ee93e..0397542d45 100644 --- a/README.md +++ b/README.md @@ -347,7 +347,7 @@ _Static site generator is a software that takes some text + templates as input a _Libraries for working with HTTP._ -- General +- Clients - [requests](https://github.com/psf/requests) - HTTP Requests for Humans. - [httpx](https://github.com/encode/httpx) - A next generation HTTP client for Python. - [aiohttp](https://github.com/aio-libs/aiohttp) - Asynchronous HTTP client/server framework for asyncio and Python. From 41f89f7f1149321261d91dc8741c32fe7ce9c030 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:23:56 +0800 Subject: [PATCH 049/168] audit: sweep ORM to the shortlist cap Relational Databases had 7 entries against the cap of 5. Removed: - dataset (2,316,477 downloads/month) - dict-store convenience wrapper, not the ORM job - pony (653,675 downloads/month) - fading mindshare, no successor trajectory; repo still active, this is a cap call not an abandonment call - tortoise-orm (599,872 downloads/month, flat) - async niche now served by SQLAlchemy asyncio and sqlmodel Downloads are PyPI last-30-day via ClickPy fetched 2026-08-16. Both subcategories reordered per entry-ordering rule: obvious choices by downloads descending (sqlalchemy 423.9M, django.db.models riding django 56.1M, peewee 50.8M; pynamodb 4.1M, mongoengine 2.5M) then challengers (sqlmodel 22.3M; beanie 1.6M). Co-Authored-By: Claude --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0397542d45..28b836b54e 100644 --- a/README.md +++ b/README.md @@ -382,18 +382,15 @@ _Libraries for sending and parsing email, and mail server management._ _Libraries that implement Object-Relational Mapping or data mapping techniques._ - Relational Databases - - [django.db.models](https://github.com/django/django) - The Django [ORM](https://docs.djangoproject.com/en/dev/topics/db/models/). - [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) - The Python SQL Toolkit and Object Relational Mapper. - [awesome-sqlalchemy](https://github.com/dahlia/awesome-sqlalchemy) - - [dataset](https://github.com/pudo/dataset) - Store Python dicts in a database - works with SQLite, MySQL, and PostgreSQL. + - [django.db.models](https://github.com/django/django) - The Django [ORM](https://docs.djangoproject.com/en/dev/topics/db/models/). - [peewee](https://github.com/coleifer/peewee) - A small, expressive ORM. - - [pony](https://github.com/ponyorm/pony/) - ORM that provides a generator-oriented interface to SQL. - [sqlmodel](https://github.com/fastapi/sqlmodel) - SQLModel is based on Python type annotations, and powered by Pydantic and SQLAlchemy. - - [tortoise-orm](https://github.com/tortoise/tortoise-orm) - An easy-to-use asyncio ORM inspired by Django, with relations support. - NoSQL Databases - - [beanie](https://github.com/BeanieODM/beanie) - An asynchronous Python object-document mapper (ODM) for MongoDB. - - [mongoengine](https://github.com/MongoEngine/mongoengine) - A Python Object-Document-Mapper for working with MongoDB. - [pynamodb](https://github.com/pynamodb/PynamoDB) - A Pythonic interface for [Amazon DynamoDB](https://aws.amazon.com/dynamodb/). + - [mongoengine](https://github.com/MongoEngine/mongoengine) - A Python Object-Document-Mapper for working with MongoDB. + - [beanie](https://github.com/BeanieODM/beanie) - An asynchronous Python object-document mapper (ODM) for MongoDB. ### Database Drivers From b8dd6538c250c1aabf288ef5ee21e7dd2e5d1f9b Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:26:28 +0800 Subject: [PATCH 050/168] style: restructure Database Drivers section Database & Storage audit (maintainer adjudicated 2026-08-16), format-only outcome, no removals: - Mint a ClickHouse subcategory between SQLite and Other Relational Databases, moving clickhouse-driver into it; two ClickHouse clients justify their own use case (official clickhouse-connect lands next as its own add commit). - Rename entry redis-py to redis per the PyPI-package-name naming rule in CONTRIBUTING.md; also fixes a NOT_FOUND row in every downloads sweep. - Reorder MySQL (pymysql 96.4M downloads/month before mysqlclient 20.4M) and NoSQL Databases (redis 277M pepy, pymongo 116.6M, cassandra-driver 8.0M, then django-mongodb-backend 31K as challenger) per the entry-ordering rule. Co-Authored-By: Claude --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 28b836b54e..c9f85f53b2 100644 --- a/README.md +++ b/README.md @@ -397,21 +397,22 @@ _Libraries that implement Object-Relational Mapping or data mapping techniques._ _Libraries for connecting and operating databases._ - MySQL - [awesome-mysql](https://github.com/shlomi-noach/awesome-mysql) - - [mysqlclient](https://github.com/PyMySQL/mysqlclient) - MySQL connector with Python 3 support ([mysql-python](https://sourceforge.net/projects/mysql-python/) fork). - [pymysql](https://github.com/PyMySQL/PyMySQL) - A pure Python MySQL driver compatible to mysql-python. + - [mysqlclient](https://github.com/PyMySQL/mysqlclient) - MySQL connector with Python 3 support ([mysql-python](https://sourceforge.net/projects/mysql-python/) fork). - PostgreSQL - [awesome-postgres](https://github.com/dhamaniasad/awesome-postgres) - [psycopg](https://github.com/psycopg/psycopg) - The most popular PostgreSQL adapter for Python. - SQLite - [awesome-sqlite](https://github.com/planetopendata/awesome-sqlite) - [sqlite-utils](https://github.com/simonw/sqlite-utils) - Python CLI utility and library for manipulating SQLite databases. - [sqlite3](https://docs.python.org/3/library/sqlite3.html) - (Python standard library) SQLite interface compliant with DB-API 2.0. -- Other Relational Databases +- ClickHouse - [clickhouse-driver](https://github.com/mymarilyn/clickhouse-driver) - Python driver with native interface for ClickHouse. +- Other Relational Databases - [mssql-python](https://github.com/microsoft/mssql-python) - Official Microsoft driver for SQL Server and Azure SQL, built on ODBC for high performance and low memory usage. - NoSQL Databases + - [redis](https://github.com/redis/redis-py) - The Python client for Redis. + - [pymongo](https://github.com/mongodb/mongo-python-driver) - The official Python client for MongoDB. - [cassandra-driver](https://github.com/apache/cassandra-python-driver) - The Python Driver for Apache Cassandra. - [django-mongodb-backend](https://github.com/mongodb/django-mongodb-backend) - Official MongoDB database backend for Django. - - [pymongo](https://github.com/mongodb/mongo-python-driver) - The official Python client for MongoDB. - - [redis-py](https://github.com/redis/redis-py) - The Python client for Redis. ### Database From 0cc4e0eed4d588379d0779efb7499b8d118fa392 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:27:18 +0800 Subject: [PATCH 051/168] feat: add asyncpg to Database Drivers > PostgreSQL MagicStack's asyncio PostgreSQL driver, 122,401,686 downloads/month (pepy.tech, fetched 2026-08-16). Verified as obvious choice #2 behind psycopg (130.8M downloads/month, same source) in the Database & Storage audit; last push 2026-02, inside the 12-month Active rule. Its absence was a gap in the list. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c9f85f53b2..16203b791c 100644 --- a/README.md +++ b/README.md @@ -401,6 +401,7 @@ _Libraries for connecting and operating databases._ - [mysqlclient](https://github.com/PyMySQL/mysqlclient) - MySQL connector with Python 3 support ([mysql-python](https://sourceforge.net/projects/mysql-python/) fork). - PostgreSQL - [awesome-postgres](https://github.com/dhamaniasad/awesome-postgres) - [psycopg](https://github.com/psycopg/psycopg) - The most popular PostgreSQL adapter for Python. + - [asyncpg](https://github.com/MagicStack/asyncpg) - A fast PostgreSQL Database Client Library for Python/asyncio. - SQLite - [awesome-sqlite](https://github.com/planetopendata/awesome-sqlite) - [sqlite-utils](https://github.com/simonw/sqlite-utils) - Python CLI utility and library for manipulating SQLite databases. - [sqlite3](https://docs.python.org/3/library/sqlite3.html) - (Python standard library) SQLite interface compliant with DB-API 2.0. From 774da7236e35e241f75ec51d5e9fe7673b28b67f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:28:05 +0800 Subject: [PATCH 052/168] feat: add clickhouse-connect to Database Drivers > ClickHouse Database & Storage audit (2026-08-16): official ClickHouse client at 31,797,323 downloads/month has overtaken community clickhouse-driver at 18,405,937/month (pepy.tech, same source, fetched 2026-08-16). Listed first per entry-ordering rule; clickhouse-driver stays second tier. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 16203b791c..adf4882b96 100644 --- a/README.md +++ b/README.md @@ -406,6 +406,7 @@ _Libraries for connecting and operating databases._ - [sqlite-utils](https://github.com/simonw/sqlite-utils) - Python CLI utility and library for manipulating SQLite databases. - [sqlite3](https://docs.python.org/3/library/sqlite3.html) - (Python standard library) SQLite interface compliant with DB-API 2.0. - ClickHouse + - [clickhouse-connect](https://github.com/ClickHouse/clickhouse-connect) - The official ClickHouse client, with SQLAlchemy and Superset connectors. - [clickhouse-driver](https://github.com/mymarilyn/clickhouse-driver) - Python driver with native interface for ClickHouse. - Other Relational Databases - [mssql-python](https://github.com/microsoft/mssql-python) - Official Microsoft driver for SQL Server and Azure SQL, built on ODBC for high performance and low memory usage. From 9b28c566bfbfaa0d1b857c0eba39e104bc9dc72a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:28:45 +0800 Subject: [PATCH 053/168] feat: add pyodbc to Other Relational Databases SQL Server / ODBC standard for two decades, 42,911,527 downloads/month (pepy.tech, fetched 2026-08-16). Its absence was a gap in the list from the Database & Storage audit, not a verdict on the project. Listed as obvious choice #1, before mssql-python (3.3M/month challenger), per entry-ordering rule. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index adf4882b96..676e8e6046 100644 --- a/README.md +++ b/README.md @@ -409,6 +409,7 @@ _Libraries for connecting and operating databases._ - [clickhouse-connect](https://github.com/ClickHouse/clickhouse-connect) - The official ClickHouse client, with SQLAlchemy and Superset connectors. - [clickhouse-driver](https://github.com/mymarilyn/clickhouse-driver) - Python driver with native interface for ClickHouse. - Other Relational Databases + - [pyodbc](https://github.com/mkleehammer/pyodbc) - An ODBC bridge for connecting to SQL Server and any other ODBC-accessible database. - [mssql-python](https://github.com/microsoft/mssql-python) - Official Microsoft driver for SQL Server and Azure SQL, built on ODBC for high performance and low memory usage. - NoSQL Databases - [redis](https://github.com/redis/redis-py) - The Python client for Redis. From 442291d74a3941c0c0b5745181353882e35484e8 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:29:30 +0800 Subject: [PATCH 054/168] feat: add oracledb to Database Drivers > Other Relational Databases Oracle's official driver, successor to cx_Oracle. 26,856,874 downloads/month (pepy.tech, fetched 2026-08-16), from the Database & Storage audit (maintainer adjudicated 2026-08-16). Placed as obvious choice #2 between pyodbc (42.9M) and challenger mssql-python (3.3M) per entry-ordering rule. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 676e8e6046..8a3e366763 100644 --- a/README.md +++ b/README.md @@ -410,6 +410,7 @@ _Libraries for connecting and operating databases._ - [clickhouse-driver](https://github.com/mymarilyn/clickhouse-driver) - Python driver with native interface for ClickHouse. - Other Relational Databases - [pyodbc](https://github.com/mkleehammer/pyodbc) - An ODBC bridge for connecting to SQL Server and any other ODBC-accessible database. + - [oracledb](https://github.com/oracle/python-oracledb) - The official Python driver for Oracle Database, successor to cx_Oracle. - [mssql-python](https://github.com/microsoft/mssql-python) - Official Microsoft driver for SQL Server and Azure SQL, built on ODBC for high performance and low memory usage. - NoSQL Databases - [redis](https://github.com/redis/redis-py) - The Python client for Redis. From 3a3b20c03debe880259b0e9e5bf8de901ae1215b Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:30:29 +0800 Subject: [PATCH 055/168] audit: sweep Database to the shortlist cap Split the flat Database section into three subcategories (Analytical, Vector, Key-Value & Document) since its 7 entries exceeded the shortlist cap of 5 and the size reflected genuinely distinct jobs: - Analytical: duckdb (obvious choice, 61,026,806 downloads/month), chdb (challenger, 3,564,786 downloads/month) - Vector: chromadb (obvious choice, 13,048,822 downloads/month), zvec (challenger on star trajectory, 44,737 downloads/month, 15.4K stars in 8 months) - Key-Value & Document: tinydb (obvious choice, 6,194,854 downloads/month) Removed: - pickledb (29,446 downloads/month) - toy key-value store - ZODB (197,044 downloads/month) - Zope-era native object database nobody names unprompted in 2026; repo still active, this is a relevance call, not an abandonment call Rewrote the section description from "Databases implemented in Python" to "In-process databases usable directly from Python" because duckdb, chdb, and zvec are not themselves implemented in Python, and the written-in-Python scope test was already removed from CONTRIBUTING.md. Downloads are PyPI last-30-day via ClickPy, fetched 2026-08-16. Co-Authored-By: Claude --- README.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 8a3e366763..7f7f48e1ec 100644 --- a/README.md +++ b/README.md @@ -420,15 +420,16 @@ _Libraries for connecting and operating databases._ ### Database -_Databases implemented in Python._ - -- [chdb](https://github.com/chdb-io/chdb) - In-process OLAP SQL engine with the full ClickHouse dialect, zero-copy pandas/Arrow interop, and federation to remote ClickHouse clusters via `remoteSecure()`. -- [chromadb](https://github.com/chroma-core/chroma) - An open-source embedding database for building AI applications with embeddings and semantic search. -- [duckdb](https://github.com/duckdb/duckdb) - An in-process SQL OLAP database management system; optimized for analytics and fast queries, similar to SQLite but for analytical workloads. -- [pickledb](https://github.com/patx/pickledb) - A simple and lightweight key-value store for Python. -- [tinydb](https://github.com/msiemens/tinydb) - A tiny, document-oriented database. -- [ZODB](https://github.com/zopefoundation/ZODB) - A native object database for Python. A key-value and object graph database. -- [zvec](https://github.com/alibaba/zvec) - An embedded vector database for on-device RAG and edge AI, the SQLite of vector databases. +_In-process databases usable directly from Python._ + +- Analytical + - [duckdb](https://github.com/duckdb/duckdb) - An in-process SQL OLAP database management system; optimized for analytics and fast queries, similar to SQLite but for analytical workloads. + - [chdb](https://github.com/chdb-io/chdb) - In-process OLAP SQL engine with the full ClickHouse dialect, zero-copy pandas/Arrow interop, and federation to remote ClickHouse clusters via `remoteSecure()`. +- Vector + - [chromadb](https://github.com/chroma-core/chroma) - An open-source embedding database for building AI applications with embeddings and semantic search. + - [zvec](https://github.com/alibaba/zvec) - An embedded vector database for on-device RAG and edge AI, the SQLite of vector databases. +- Key-Value & Document + - [tinydb](https://github.com/msiemens/tinydb) - A tiny, document-oriented database. ### Caching From b7b633d509dc9c3e728372401e72905bc3c0e1ca Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:31:17 +0800 Subject: [PATCH 056/168] feat: add lancedb to Database & Storage > Vector Adds lancedb as obvious choice #2 in Vector, from the Database & Storage audit (maintainer adjudicated 2026-08-16): embedded vector database for multimodal AI, 9,315,269 downloads/month (pepy.tech, fetched 2026-08-16), 11.2K stars, very active (pushed 2026-08-15). Same-source check keeps chromadb first (13.3M pepy); zvec stays last as trajectory challenger. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7f7f48e1ec..bf06dc314a 100644 --- a/README.md +++ b/README.md @@ -427,6 +427,7 @@ _In-process databases usable directly from Python._ - [chdb](https://github.com/chdb-io/chdb) - In-process OLAP SQL engine with the full ClickHouse dialect, zero-copy pandas/Arrow interop, and federation to remote ClickHouse clusters via `remoteSecure()`. - Vector - [chromadb](https://github.com/chroma-core/chroma) - An open-source embedding database for building AI applications with embeddings and semantic search. + - [lancedb](https://github.com/lancedb/lancedb) - A developer-friendly embedded retrieval database for multimodal AI. - [zvec](https://github.com/alibaba/zvec) - An embedded vector database for on-device RAG and edge AI, the SQLite of vector databases. - Key-Value & Document - [tinydb](https://github.com/msiemens/tinydb) - A tiny, document-oriented database. From 02735b6ced75d686cc2897ff802ebd036dfe2f2a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:32:02 +0800 Subject: [PATCH 057/168] style: reorder Caching by downloads, rename python-diskcache to diskcache Caching section audit (maintainer adjudicated 2026-08-16, format-only): - Renamed python-diskcache to diskcache to match its PyPI package name per CONTRIBUTING.md naming rule; also fixes a NOT_FOUND row in every downloads sweep. - Reordered by monthly downloads (pepy): cachetools (338,290,732) and diskcache (38,755,627) as obvious choices, then dogpile.cache (2,460,237) and django-cacheops (1,728,494) as second-tier challengers. - Maintainer confirmed keeping diskcache despite the repo being dormant since 2024-08: 38.8M downloads/month and nothing succeeds it at its job. Co-Authored-By: Claude --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bf06dc314a..48f1deb0f2 100644 --- a/README.md +++ b/README.md @@ -437,9 +437,9 @@ _In-process databases usable directly from Python._ _Libraries for caching data._ - [cachetools](https://github.com/tkem/cachetools) - Extensible memoizing collections and decorators. -- [django-cacheops](https://github.com/Suor/django-cacheops) - A slick ORM cache with automatic granular event-driven invalidation. +- [diskcache](https://github.com/grantjenks/python-diskcache) - SQLite and file backed cache backend with faster lookups than memcached and redis. - [dogpile.cache](https://github.com/sqlalchemy/dogpile.cache) - dogpile.cache is a next generation replacement for Beaker made by the same authors. -- [python-diskcache](https://github.com/grantjenks/python-diskcache) - SQLite and file backed cache backend with faster lookups than memcached and redis. +- [django-cacheops](https://github.com/Suor/django-cacheops) - A slick ORM cache with automatic granular event-driven invalidation. ### Search From 7ac2950dc63a7c14a68062ff646b0b996141e0cb Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:32:47 +0800 Subject: [PATCH 058/168] audit: sweep Search to the shortlist cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed pysolr (352,069 downloads/month via ClickPy, 347,571 pepy same-source, fetched 2026-08-16) — lightweight Apache Solr wrapper, the Solr era passed. Renamed elasticsearch-py to elasticsearch per the PyPI-package-name naming rule in CONTRIBUTING.md; also fixes a NOT_FOUND row in every downloads sweep. Reordered: elasticsearch (54,160,230/month pepy) obvious choice first, django-haystack (194,205/month pepy) kept and moved to second tier per maintainer's tier call during verdict review. Co-Authored-By: Claude --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 48f1deb0f2..296401ec42 100644 --- a/README.md +++ b/README.md @@ -445,9 +445,8 @@ _Libraries for caching data._ _Libraries and software for indexing and performing search queries on data._ +- [elasticsearch](https://github.com/elastic/elasticsearch-py) - The official low-level Python client for [Elasticsearch](https://www.elastic.co/products/elasticsearch). - [django-haystack](https://github.com/django-haystack/django-haystack) - Modular search for Django. -- [elasticsearch-py](https://github.com/elastic/elasticsearch-py) - The official low-level Python client for [Elasticsearch](https://www.elastic.co/products/elasticsearch). -- [pysolr](https://github.com/django-haystack/pysolr) - A lightweight Python wrapper for [Apache Solr](https://lucene.apache.org/solr/). ### Serialization From f9539567030d527ce117c36506e3dff594a4ca3a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:33:25 +0800 Subject: [PATCH 059/168] feat: add opensearch-py to Search as obvious choice Database & Storage audit (2026-08-16): opensearch-py is the official low-level client of the OpenSearch fork, 52,432,831 downloads/month, near parity with elasticsearch at 54,160,230/month (both pepy.tech, fetched 2026-08-16). Placed after elasticsearch, before second-tier django-haystack, per entry-ordering rule. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 296401ec42..d96248bf95 100644 --- a/README.md +++ b/README.md @@ -446,6 +446,7 @@ _Libraries for caching data._ _Libraries and software for indexing and performing search queries on data._ - [elasticsearch](https://github.com/elastic/elasticsearch-py) - The official low-level Python client for [Elasticsearch](https://www.elastic.co/products/elasticsearch). +- [opensearch-py](https://github.com/opensearch-project/opensearch-py) - The official low-level Python client for [OpenSearch](https://opensearch.org/). - [django-haystack](https://github.com/django-haystack/django-haystack) - Modular search for Django. ### Serialization From 509fcaa38420704674606646c8405a22ede503ef Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:34:08 +0800 Subject: [PATCH 060/168] feat: add meilisearch to Search as a challenger Official Python client for the Meilisearch engine, 1,107,508 downloads/month (pepy.tech, fetched 2026-08-16). Admitted on the engine's developer-tool adoption trajectory; flagged as the weakest add of the Database & Storage audit (maintainer adjudicated 2026-08-16) and a judgment call in the reviewed verdicts. Placed after the obvious choices (elasticsearch, opensearch-py), before second-tier django-haystack, per entry-ordering rule. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d96248bf95..4c49e77fe9 100644 --- a/README.md +++ b/README.md @@ -447,6 +447,7 @@ _Libraries and software for indexing and performing search queries on data._ - [elasticsearch](https://github.com/elastic/elasticsearch-py) - The official low-level Python client for [Elasticsearch](https://www.elastic.co/products/elasticsearch). - [opensearch-py](https://github.com/opensearch-project/opensearch-py) - The official low-level Python client for [OpenSearch](https://opensearch.org/). +- [meilisearch](https://github.com/meilisearch/meilisearch-python) - The official Python client for the [Meilisearch](https://www.meilisearch.com/) search engine. - [django-haystack](https://github.com/django-haystack/django-haystack) - Modular search for Django. ### Serialization From 745347dcddbcf170ad94d59dfe22fbcbeb7cc3cb Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:34:52 +0800 Subject: [PATCH 061/168] style: reorder Serialization by downloads Audit outcome of the Database & Storage sitting, maintainer adjudicated 2026-08-16, format-only. Reordered from alphabetical to the entry-ordering rule: obvious choices by downloads/month descending, then challenger. msgpack 290,175,972; orjson 234,189,977; marshmallow 122,497,803; msgspec (challenger) 43,745,974. PyPI last-30-day downloads via ClickPy, fetched 2026-08-16. Co-Authored-By: Claude --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4c49e77fe9..6afb341b86 100644 --- a/README.md +++ b/README.md @@ -454,10 +454,10 @@ _Libraries and software for indexing and performing search queries on data._ _Libraries for serializing complex data types._ -- [marshmallow](https://github.com/marshmallow-code/marshmallow) - A lightweight library for converting complex objects to and from simple Python datatypes. - [msgpack](https://github.com/msgpack/msgpack-python) - MessagePack serializer implementation for Python. -- [msgspec](https://github.com/msgspec/msgspec) - A fast serialization and validation library with built-in support for JSON, MessagePack, YAML, and TOML. - [orjson](https://github.com/ijl/orjson) - Fast, correct JSON library. +- [marshmallow](https://github.com/marshmallow-code/marshmallow) - A lightweight library for converting complex objects to and from simple Python datatypes. +- [msgspec](https://github.com/msgspec/msgspec) - A fast serialization and validation library with built-in support for JSON, MessagePack, YAML, and TOML. **Data & Science** From 5da1d16de1c8ef17f653d31f9f11c5e6a431c333 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:40:44 +0800 Subject: [PATCH 062/168] docs: define Second Tier in CONTEXT.md The 2026-08-16 Database & Storage audit exposed a vocabulary gap: four adjudicated entries (clickhouse-driver, dogpile.cache, django-cacheops, django-haystack) are neither Obvious Choices nor trajectory-backed Challengers but demoted incumbents occupying Challenger slots, and the sitting had to improvise the term. The maintainer ratified it during review. A demoted incumbent counts against the two Challenger slots, but the adoption-trajectory bar gates only new admissions, not demotions. Also from the same sitting: psycopg2 was deliberately left unlisted under Database Drivers > PostgreSQL (282M downloads/month as psycopg2-binary, pepy 2026-08-16) because psycopg 3 is the new-work answer and v2 is legacy install base. Recorded here so the next PostgreSQL audit knows it was a decision, not an oversight. Co-Authored-By: Claude --- CONTEXT.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CONTEXT.md b/CONTEXT.md index f4b23b2c31..c6deb3cc1c 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -47,6 +47,9 @@ _Avoid_: One-in-one-out (informal alias) An entry (at most two per Use Case) that is not yet the Obvious Choice but is a credible successor to one. Marked by ordering, not description: within a Use Case, Obvious Choices are listed first, then Challengers, each tier by PyPI downloads/month descending (no-signal entries last in tier, alphabetically). Admission requires adoption-trajectory evidence, not popularity alone. _Avoid_: Rising Star (old lane name), Hidden Gem (old lane name — concept removed entirely) +**Second Tier**: +A Challenger slot holding a demoted incumbent instead of a rising successor — a former Obvious Choice or fading community standard an Audit kept below the current Obvious Choices (clickhouse-driver behind the official client, dogpile.cache and django-cacheops behind cachetools and diskcache, django-haystack in Search). It counts against the two Challenger slots and is marked by position like any Challenger; the adoption-trajectory bar gates only new admissions, not demotions. + **Split**: Maintainer-only restructuring of an oversized Use Case into finer Use Cases (new Subcategories), considered before any trimming when the size reflects genuinely distinct jobs. A submitter's entry PR can never perform a Split. From bc3e7a08cd7b46b22061b3453283ecd00964470d Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:45:31 +0800 Subject: [PATCH 063/168] docs: condense AGENTS.md and CLAUDE.md for progressive disclosure Trim repository overview and structure sections into a brief intro plus focused Entry Rules and Gotchas sections, dropping restated CONTRIBUTING.md content and Makefile/pyproject boilerplate. Co-Authored-By: Claude --- AGENTS.md | 33 ++++++++------------------------- CLAUDE.md | 33 ++++++++------------------------- 2 files changed, 16 insertions(+), 50 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 646889dc08..af55f4d922 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,32 +1,15 @@ # AGENTS.md -## Repository Overview +An opinionated shortlist of Python frameworks, libraries, tools, and resources, published at [awesome-python.com](https://awesome-python.com/). README.md is the single source of truth for catalog entries and README sponsor placements; `website/` renders it into the static site. -An opinionated list of Python frameworks, libraries, tools, and resources. Published at [awesome-python.com](https://awesome-python.com/). +## Entry Rules -## Entry Guidelines +[CONTRIBUTING.md](CONTRIBUTING.md) holds the admission rules, quality requirements, rejection rules, entry format, and ordering. Apply it whenever adding or removing an entry — direct commits included, not only PR reviews. -**Refer to [CONTRIBUTING.md](CONTRIBUTING.md)** for admission rules, quality requirements, rejection rules, and entry format. Apply these rules whenever adding or removing an entry, whether reviewing a PR or committing directly. +- Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Training-data recollections are not evidence; label anything unverifiable as a judgment call. +- One entry per commit when adding or deleting entries. Exceptions: a prune sweep is one commit per section, its body listing each removal with its reason; format, wording, or categorization changes may be bundled. +- Sponsor placement never influences which projects get listed — see [SPONSORSHIP.md](SPONSORSHIP.md). `website/templates/sponsorship.html` separately defines the sponsorship content on the published website page. -## Structure +## Gotchas -- **README.md**: Source of truth for catalog entries and README sponsor placements. Hierarchical categories; entries ordered per the Key Rules below. -- **CONTRIBUTING.md**: Submission guidelines and review criteria. -- **SPONSORSHIP.md**: Sponsor tiers, placement rules, and the editorial-independence policy. `website/templates/sponsorship.html` separately defines which sponsorship content appears on the published website page. -- **website/**: Static site generator that builds awesome-python.com from README.md. - - `build.py`: Parses README.md and renders HTML via Jinja2 templates. - - `fetch_github_stars.py`: Fetches star counts into `website/data/`. - - `readme_parser.py`: Markdown-to-structured-data parser. - - `templates/`, `static/`: Jinja2 templates and CSS/JS assets. - - `tests/`: Pytest tests for the build pipeline. -- **Makefile**: `make install`, `make build`, `make preview`, `make test`, `make lint`, `make format`, `make typecheck`, `make fetch_github_stars`. On machines with only Python 3.14, prefix uv-based targets with `UV_PYTHON=3.13` (watchdog 6.0.0 ships no 3.14 wheel and the project sets `no-build`). -- **pyproject.toml**: Uses `uv` for dependency management. Python >=3.13. - -## Key Rules - -- Ordering within a use case: obvious choices first, then challengers, each tier by PyPI downloads/month descending; no-signal entries last in tier, alphabetically. See CONTRIBUTING.md. -- A shortlist, not a catalog: per use case, up to 3 obvious choices plus up to 2 challengers, hard maximum 5. -- One project per PR. -- One entry per commit when adding or deleting entries. Exception: a prune sweep is one commit per section, its body listing each removal with its reason. Format, wording, or categorization changes across multiple entries may be bundled in a single commit. -- Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Training-data recollections alone are not evidence; verify before stating, and label anything unverifiable as a judgment call. -- README.md is the source of truth for catalog entries and README sponsor placements; treat `SPONSORSHIP.md` and `website/templates/sponsorship.html` as separate sponsorship content surfaces. +- On machines with only Python 3.14, prefix uv-based make targets with `UV_PYTHON=3.13` — watchdog 6.0.0 ships no 3.14 wheel and the project sets `no-build`. diff --git a/CLAUDE.md b/CLAUDE.md index 52b9391c3a..67117dd97b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,32 +1,15 @@ # CLAUDE.md -## Repository Overview +An opinionated shortlist of Python frameworks, libraries, tools, and resources, published at [awesome-python.com](https://awesome-python.com/). README.md is the single source of content truth; `website/` renders it into the static site. -An opinionated list of Python frameworks, libraries, tools, and resources. Published at [awesome-python.com](https://awesome-python.com/). +## Entry Rules -## Entry Guidelines +[CONTRIBUTING.md](CONTRIBUTING.md) holds the admission rules, quality requirements, rejection rules, entry format, and ordering. Apply it whenever adding or removing an entry — direct commits included, not only PR reviews. -**Refer to [CONTRIBUTING.md](CONTRIBUTING.md)** for admission rules, quality requirements, rejection rules, and entry format. Apply these rules whenever adding or removing an entry, whether reviewing a PR or committing directly. +- Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Training-data recollections are not evidence; label anything unverifiable as a judgment call. +- One entry per commit when adding or deleting entries. Exceptions: a prune sweep is one commit per section, its body listing each removal with its reason; format, wording, or categorization changes may be bundled. +- Sponsor placement never influences which projects get listed — see [SPONSORSHIP.md](SPONSORSHIP.md). -## Structure +## Gotchas -- **README.md**: Source of truth. Hierarchical categories; entries ordered per the Key Rules below. -- **CONTRIBUTING.md**: Submission guidelines and review criteria. -- **SPONSORSHIP.md**: Sponsor tiers, placement rules, and the editorial-independence policy. Sponsor content sits in the README header and must never influence which projects get listed. -- **website/**: Static site generator that builds awesome-python.com from README.md. - - `build.py`: Parses README.md and renders HTML via Jinja2 templates. - - `fetch_github_stars.py`: Fetches star counts into `website/data/`. - - `readme_parser.py`: Markdown-to-structured-data parser. - - `templates/`, `static/`: Jinja2 templates and CSS/JS assets. - - `tests/`: Pytest tests for the build pipeline. -- **Makefile**: `make install`, `make build`, `make preview`, `make test`, `make lint`, `make format`, `make typecheck`, `make fetch_github_stars`. On machines with only Python 3.14, prefix uv-based targets with `UV_PYTHON=3.13` (watchdog 6.0.0 ships no 3.14 wheel and the project sets `no-build`). -- **pyproject.toml**: Uses `uv` for dependency management. Python >=3.13. - -## Key Rules - -- Ordering within a use case: obvious choices first, then challengers, each tier by PyPI downloads/month descending; no-signal entries last in tier, alphabetically. See CONTRIBUTING.md. -- A shortlist, not a catalog: per use case, up to 3 obvious choices plus up to 2 challengers, hard maximum 5. -- One project per PR. -- One entry per commit when adding or deleting entries. Exception: a prune sweep is one commit per section, its body listing each removal with its reason. Format, wording, or categorization changes across multiple entries may be bundled in a single commit. -- Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Training-data recollections alone are not evidence; verify before stating, and label anything unverifiable as a judgment call. -- README.md is the single source of content truth. +- On machines with only Python 3.14, prefix uv-based make targets with `UV_PYTHON=3.13` — watchdog 6.0.0 ships no 3.14 wheel and the project sets `no-build`. From 6c93b1e588d749b1c153a5ed284c221437ce618c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:45:34 +0800 Subject: [PATCH 064/168] docs: update audit-the-list SKILL.md wording Broaden argument-hint to cover thematic groups alongside sections, and backtick tool/skill names for consistency. Co-Authored-By: Claude --- .claude/skills/audit-the-list/SKILL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude/skills/audit-the-list/SKILL.md b/.claude/skills/audit-the-list/SKILL.md index be48f239f8..bad39c1934 100644 --- a/.claude/skills/audit-the-list/SKILL.md +++ b/.claude/skills/audit-the-list/SKILL.md @@ -1,7 +1,7 @@ --- name: audit-the-list description: Audit README.md sections against the shortlist rules — re-verify every entry's verdict with live data, promote or demote challengers, restructure oversized use cases, prune, and evaluate proposed additions. Fire when the maintainer asks to audit, sweep, prune, re-check, or maintain sections, or asks whether an entry (or a proposed one) deserves its slot. -argument-hint: [all sections or specific sections] +argument-hint: [all or specific groups or sections] --- # Audit the list @@ -10,7 +10,7 @@ An Audit re-runs the admission test over live sections of README.md: every entry ## 1. Scope -Resolve the scope from the arguments. Named sections mean exactly those, whether or not they were audited before (a re-run is how a past verdict gets rechecked). `all` is ambiguous — AskUserQuestion whether it means every section or only never-audited ones; prior audits are recorded in git history (`git log --oneline --grep="sweep\|audit"`). With no arguments, AskUserQuestion listing the never-audited Thematic Groups. Batch the work one Thematic Group per sitting. Done when the section list is settled. +Resolve the scope from the arguments. Named sections mean exactly those, whether or not they were audited before (a re-run is how a past verdict gets rechecked). `all` is ambiguous — `AskUserQuestion` whether it means every section or only never-audited ones; prior audits are recorded in git history (`git log --oneline --grep="sweep\|audit"`). With no arguments, AskUserQuestion listing the never-audited Thematic Groups. Batch the work one Thematic Group per sitting. Done when the section list is settled. ## 2. Evidence @@ -28,7 +28,7 @@ Draft a verdict and reason for every entry, restructure before cap: decide Split ## 4. Review and go -Run the preview-verdicts skill: it generates the interactive review page and defines how the maintainer's feedback JSON comes back and gets processed. Their verdicts are final. Before touching README.md, surface what the feedback implies but does not decide — cap overflows, homeless entries after a Split, tier for a tierless flip — as named assumptions or questions, then get an explicit go. +Run the `preview-verdicts` skill: it generates the interactive review page and defines how the maintainer's feedback JSON comes back and gets processed. Their verdicts are final. Before touching README.md, surface what the feedback implies but does not decide — cap overflows, homeless entries after a Split, tier for a tierless flip — as named assumptions or questions, then get an explicit go. ## 5. Execute From c6957d4c21015b9297cd00c68a496ca438737eab Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:52:03 +0800 Subject: [PATCH 065/168] docs: require WebSearch evidence for tier judgments Verifying keep/drop reasons with download counts alone isn't enough to judge obvious-choice vs challenger tiers; the maintainer requires WebSearch evidence of adoption trajectory and community sentiment too. Also rewrites the repo overview in CLAUDE.md and mirrors it to AGENTS.md per the kept-in-sync convention. Co-Authored-By: Claude --- AGENTS.md | 6 ++++-- CLAUDE.md | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index af55f4d922..146958659e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,12 +1,14 @@ # AGENTS.md -An opinionated shortlist of Python frameworks, libraries, tools, and resources, published at [awesome-python.com](https://awesome-python.com/). README.md is the single source of truth for catalog entries and README sponsor placements; `website/` renders it into the static site. +An opinionated guide to the best Python frameworks, libraries, tools, and resources. + +[README.md](README.md) is the single source of truth for catalog entries and README sponsor placements; `website/` renders it into the static site: [awesome-python.com](https://awesome-python.com/). ## Entry Rules [CONTRIBUTING.md](CONTRIBUTING.md) holds the admission rules, quality requirements, rejection rules, entry format, and ordering. Apply it whenever adding or removing an entry — direct commits included, not only PR reviews. -- Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Training-data recollections are not evidence; label anything unverifiable as a judgment call. +- Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Judging tiers — obvious choice vs challenger — also requires WebSearch evidence (adoption trajectory, community sentiment), not download counts alone. Training-data recollections are not evidence; label anything unverifiable as a judgment call. - One entry per commit when adding or deleting entries. Exceptions: a prune sweep is one commit per section, its body listing each removal with its reason; format, wording, or categorization changes may be bundled. - Sponsor placement never influences which projects get listed — see [SPONSORSHIP.md](SPONSORSHIP.md). `website/templates/sponsorship.html` separately defines the sponsorship content on the published website page. diff --git a/CLAUDE.md b/CLAUDE.md index 67117dd97b..47ac9487b6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,12 +1,14 @@ # CLAUDE.md -An opinionated shortlist of Python frameworks, libraries, tools, and resources, published at [awesome-python.com](https://awesome-python.com/). README.md is the single source of content truth; `website/` renders it into the static site. +An opinionated guide to the best Python frameworks, libraries, tools, and resources. + +[README.md](README.md) is the single source of content truth; `website/` renders it into the static site: [awesome-python.com](https://awesome-python.com/). ## Entry Rules [CONTRIBUTING.md](CONTRIBUTING.md) holds the admission rules, quality requirements, rejection rules, entry format, and ordering. Apply it whenever adding or removing an entry — direct commits included, not only PR reviews. -- Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Training-data recollections are not evidence; label anything unverifiable as a judgment call. +- Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Judging tiers — obvious choice vs challenger — also requires WebSearch evidence (adoption trajectory, community sentiment), not download counts alone. Training-data recollections are not evidence; label anything unverifiable as a judgment call. - One entry per commit when adding or deleting entries. Exceptions: a prune sweep is one commit per section, its body listing each removal with its reason; format, wording, or categorization changes may be bundled. - Sponsor placement never influences which projects get listed — see [SPONSORSHIP.md](SPONSORSHIP.md). From 36c61798c499f1cdac9042d949a8f971a0ce426f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:53:24 +0800 Subject: [PATCH 066/168] update wordings --- .claude/skills/audit-the-list/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.claude/skills/audit-the-list/SKILL.md b/.claude/skills/audit-the-list/SKILL.md index bad39c1934..57285d1dee 100644 --- a/.claude/skills/audit-the-list/SKILL.md +++ b/.claude/skills/audit-the-list/SKILL.md @@ -1,7 +1,7 @@ --- name: audit-the-list description: Audit README.md sections against the shortlist rules — re-verify every entry's verdict with live data, promote or demote challengers, restructure oversized use cases, prune, and evaluate proposed additions. Fire when the maintainer asks to audit, sweep, prune, re-check, or maintain sections, or asks whether an entry (or a proposed one) deserves its slot. -argument-hint: [all or specific groups or sections] +argument-hint: [all or specific sections] --- # Audit the list From a2da2103455eeabbadcaa822313a8c19656a0b9a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 02:58:20 +0800 Subject: [PATCH 067/168] feat: stamp pypi downloads cache with fetched_at and header row Adds a header row (name, downloads, fetched_at) to data/pypi_downloads.tsv and stamps every row with the sweep date, so audits can tell evidence age and skip re-fetching when the cache is less than 7 days old. The sweep itself costs ~1s, so freshness is checked by the reader (audit-the-list skill) instead of skip logic in the fetch script. SKILL.md documents the 7-day freshness rule. Co-Authored-By: Claude --- .claude/skills/audit-the-list/SKILL.md | 2 +- website/fetch_pypi_downloads_via_clickpy.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.claude/skills/audit-the-list/SKILL.md b/.claude/skills/audit-the-list/SKILL.md index 57285d1dee..961b3c7f73 100644 --- a/.claude/skills/audit-the-list/SKILL.md +++ b/.claude/skills/audit-the-list/SKILL.md @@ -16,7 +16,7 @@ Resolve the scope from the arguments. Named sections mean exactly those, whether Fetch live evidence for every entry in scope before judging anything (CLAUDE.md verification rule): -- **Downloads/month**: `cd website && UV_PYTHON=3.13 uv run python fetch_pypi_downloads_via_clickpy.py` — free keyless ClickPy sweep of the full README, sole writer of `data/pypi_downloads.tsv` (rewritten from scratch each run). Cross-checks print to stdout, take explicit names, and never touch the cache: `fetch_pypi_downloads_via_bigquery.py ...` (canonical source, maintainer's own GCP account, `--dry-run` first — the docstring carries the cost constraints; full-README sweeps exceed the free tier, keep name lists small), `fetch_pypi_downloads_via_pepy.py ...` (needs `PEPY_TECH_API_KEY` in repo-root `.env`, throttled to 5 requests/minute), or `https://pypistats.org/api/packages/{name}/recent` paced 8s or slower. pypistats excludes mirror/CI traffic; ClickPy, BigQuery, and pepy include it — never mix sources within one comparison. +- **Downloads/month**: `cd website && UV_PYTHON=3.13 uv run python fetch_pypi_downloads_via_clickpy.py` — free keyless ClickPy sweep of the full README, sole writer of `data/pypi_downloads.tsv` (rewritten from scratch each run; header row, every row stamped with its `fetched_at` date). A cache whose `fetched_at` is within the last 7 days is current enough for verdicts — skip the sweep; older than that, re-run it (costs ~1s). Cross-checks print to stdout, take explicit names, and never touch the cache: `fetch_pypi_downloads_via_bigquery.py ...` (canonical source, maintainer's own GCP account, `--dry-run` first — the docstring carries the cost constraints; full-README sweeps exceed the free tier, keep name lists small), `fetch_pypi_downloads_via_pepy.py ...` (needs `PEPY_TECH_API_KEY` in repo-root `.env`, throttled to 5 requests/minute), or `https://pypistats.org/api/packages/{name}/recent` paced 8s or slower. pypistats excludes mirror/CI traffic; ClickPy, BigQuery, and pepy include it — never mix sources within one comparison. - **Repo state**: archived flag, last push, created date, stars, description — `gh api repos/{owner}/{repo}`, GitLab API for GitLab-hosted projects. - **PyPI metadata** (`https://pypi.org/pypi/{name}/json`) wherever a name might not be the canonical package — ownership collisions and wrong display names surface here. diff --git a/website/fetch_pypi_downloads_via_clickpy.py b/website/fetch_pypi_downloads_via_clickpy.py index e88815acb7..e384b365ed 100644 --- a/website/fetch_pypi_downloads_via_clickpy.py +++ b/website/fetch_pypi_downloads_via_clickpy.py @@ -12,7 +12,10 @@ This script is the sole writer of data/pypi_downloads.tsv and rewrites it from scratch each run, so entries removed from README.md drop out -naturally; names with no PyPI rows are written as NOT_FOUND. Cross-checks +naturally; names with no PyPI rows are written as NOT_FOUND. The file +starts with a header row (name, downloads, fetched_at) and every row +carries the sweep date: a cache fetched within the last 7 days is current +enough for audit verdicts, so only re-run when older. Cross-checks against other sources (fetch_pypi_downloads_via_bigquery.py, fetch_pypi_downloads_via_pepy.py) print to stdout and never touch the cache. @@ -21,6 +24,7 @@ """ import re +from datetime import date from pathlib import Path import httpx @@ -67,7 +71,9 @@ def main() -> None: names = collect_names(README_PATH.read_text()) print(f"Querying {len(names)} package names...") counts = fetch_clickpy(names) - OUT_FILE.write_text("\n".join(f"{name}\t{counts.get(name, 'NOT_FOUND')}" for name in names) + "\n") + fetched_at = date.today().isoformat() + rows = "\n".join(f"{name}\t{counts.get(name, 'NOT_FOUND')}\t{fetched_at}" for name in names) + OUT_FILE.write_text(f"name\tdownloads\tfetched_at\n{rows}\n") print(f"Done. {len(counts)}/{len(names)} names found on PyPI. Cached to {OUT_FILE}") From 8814a857426653100082e42a8d8fb17c2da8f412 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 03:21:04 +0800 Subject: [PATCH 068/168] feat: store verdict preview pages in repo-local ./tmp Multi-day reviews need to survive reboots, which system /tmp does not guarantee. ./tmp is git-ignored so the generated pages never land in commits. Co-Authored-By: Claude --- .claude/skills/preview-verdicts/SKILL.md | 2 +- .gitignore | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.claude/skills/preview-verdicts/SKILL.md b/.claude/skills/preview-verdicts/SKILL.md index af0de9c194..938a02d51a 100644 --- a/.claude/skills/preview-verdicts/SKILL.md +++ b/.claude/skills/preview-verdicts/SKILL.md @@ -15,7 +15,7 @@ Maintainer review happens through an interactive HTML page: one row per entry wi - `verdict` is `keep` or `drop`, seeded from the current adjudication or dry-run. - `reason` is plain language the maintainer reads cold — no invented shorthand. When fresh evidence contradicts the seeded verdict (a big download count on a drop, a dead repo on a keep), say so in that row's reason instead of silently changing the seed. 2. Copy `template.html` (sibling of this file) and replace the placeholders: `__TITLE__` (page title), `__SUB__` (sub-header: scope, seed provenance, fetch date, and the standing instruction to flip/comment then Copy feedback), `__KEY__` (localStorage key), `__DATA__` (the array). `__KEY__` must be unique per review — slug plus date, e.g. `awesome-python-science-2026-09-01` — because saved state under a reused key bleeds a previous review's flips into rows with the same section and entry name. -3. Write the page to `/tmp/awesome-python--preview.html`, `open` it, and tell the maintainer the path and the return path: flip or comment rows (they highlight yellow), press **Copy feedback**, paste the JSON into the chat. Done when the page is open and the return path is stated. +3. Write the page to `tmp/awesome-python--preview.html` in the repo root (git-ignored; create the directory if needed), `open` it, and tell the maintainer the path and the return path: flip or comment rows (they highlight yellow), press **Copy feedback**, paste the JSON into the chat. Done when the page is open and the return path is stated. ## Process the pasted feedback diff --git a/.gitignore b/.gitignore index ab400a0226..b4d552e4f0 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ docs/* !docs/adr/ # agents +tmp/ .superpowers/ .playwright-cli/ skills-lock.json From 3e90482f01b223550b69eb8e30ab0a4f9d7af4c2 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 11:52:55 +0800 Subject: [PATCH 069/168] audit: sweep Code Analysis to the shortlist cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed code2flow (36,486 downloads/month, last push 2025-07 — fails the obvious-choice bar, same test as dropped peers). Removed pytype (919,951 downloads/month — Google sunset, maintenance mode, Python 3.12 is the last supported version). Merged Code Linters + Code Formatters into one Linters and Formatters use case (ruff is the 2026 de facto standard for both; tiers: ruff/black/isort obvious choices, pylint/flake8 second tier). Re-homed bandit to new Security Linters subcategory (security linting is a distinct job from style linting). Demoted typeshed to sub-item under mypy (stub infrastructure every checker consumes, not itself a checker holding a slot). Promoted ty to obvious choice (maintainer call), order mypy/ty then pyrefly challenger. Reordered Code Analysis subcategory vulture first (12.3M/month obvious choice, prospector 485K and repowise 33K challengers — repowise kept on maintainer flip). Co-Authored-By: Claude --- README.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6afb341b86..c08fc9ea07 100644 --- a/README.md +++ b/README.md @@ -584,29 +584,27 @@ _Interactive Python interpreters (REPL)._ _Tools of static analysis, linters and code quality checkers. Also see [awesome-static-analysis](https://github.com/analysis-tools-dev/static-analysis)._ - Code Analysis - - [code2flow](https://github.com/scottrogowski/code2flow) - Turn your Python and JavaScript code into DOT flowcharts. + - [vulture](https://github.com/jendrikseipp/vulture) - A tool for finding and analyzing dead Python code. - [prospector](https://github.com/prospector-dev/prospector) - A tool to analyze Python code. - [repowise](https://github.com/repowise-dev/repowise) - Codebase intelligence that indexes repos into dependency graphs, git history, and auto-generated docs with dead code detection. - - [vulture](https://github.com/jendrikseipp/vulture) - A tool for finding and analyzing dead Python code. -- Code Linters - - [bandit](https://github.com/PyCQA/bandit) - A tool designed to find common security issues in Python code. - - [flake8](https://github.com/PyCQA/flake8) - A wrapper around `pycodestyle`, `pyflakes` and McCabe. - - [awesome-flake8-extensions](https://github.com/DmytroLitvinov/awesome-flake8-extensions) - - [pylint](https://github.com/pylint-dev/pylint) - A fully customizable source code analyzer. -- Code Formatters +- Linters and Formatters + - [ruff](https://github.com/astral-sh/ruff) - An extremely fast Python linter and code formatter. - [black](https://github.com/psf/black) - The uncompromising Python code formatter. - [isort](https://github.com/PyCQA/isort) - A Python utility / library to sort imports. - - [ruff](https://github.com/astral-sh/ruff) - An extremely fast Python linter and code formatter. + - [pylint](https://github.com/pylint-dev/pylint) - A fully customizable source code analyzer. + - [flake8](https://github.com/PyCQA/flake8) - A wrapper around `pycodestyle`, `pyflakes` and McCabe. + - [awesome-flake8-extensions](https://github.com/DmytroLitvinov/awesome-flake8-extensions) - Refactoring - [rope](https://github.com/python-rope/rope) - Rope is a python refactoring library. +- Security Linters + - [bandit](https://github.com/PyCQA/bandit) - A tool designed to find common security issues in Python code. - Type Checkers - [awesome-python-typing](https://github.com/typeddjango/awesome-python-typing) - [mypy](https://github.com/python/mypy) - Check variable types during compile time. - - [pyrefly](https://github.com/facebook/pyrefly) - A fast type checker and language server for Python. + - [typeshed](https://github.com/python/typeshed) - [ty](https://github.com/astral-sh/ty) - An extremely fast Python type checker and language server. - - [typeshed](https://github.com/python/typeshed) - Collection of library stubs for Python, with static types. + - [pyrefly](https://github.com/facebook/pyrefly) - A fast type checker and language server for Python. - Type Annotations Generators - [monkeytype](https://github.com/Instagram/MonkeyType) - A system for Python that generates static type annotations by collecting runtime types. - - [pytype](https://github.com/google/pytype) - Pytype checks and infers types for Python code - without requiring type annotations. ### Testing From 5e3d77826a987e8316d21cfd3978364537475e6b Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 11:53:30 +0800 Subject: [PATCH 070/168] feat: add pyright to Type Checkers Adjudicated by maintainer 2026-08-16: obvious choice (39.4M downloads/month via ClickPy; 2026 sources call it the strong default -- conformance lead, Pylance engine, editor integration). Ordered after ty (41.2M/month) per downloads-descending obvious-choice tier. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c08fc9ea07..6ead29ff1a 100644 --- a/README.md +++ b/README.md @@ -602,6 +602,7 @@ _Tools of static analysis, linters and code quality checkers. Also see [awesome- - [mypy](https://github.com/python/mypy) - Check variable types during compile time. - [typeshed](https://github.com/python/typeshed) - [ty](https://github.com/astral-sh/ty) - An extremely fast Python type checker and language server. + - [pyright](https://github.com/microsoft/pyright) - Full-featured static type checker for Python from Microsoft, the engine behind Pylance. - [pyrefly](https://github.com/facebook/pyrefly) - A fast type checker and language server for Python. - Type Annotations Generators - [monkeytype](https://github.com/Instagram/MonkeyType) - A system for Python that generates static type annotations by collecting runtime types. From b4960530ad83ec0784a78c02a0ac8a40b7ed6adf Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 11:54:10 +0800 Subject: [PATCH 071/168] audit: sweep Debugging Tools to the shortlist cap Developer Tools audit adjudicated by maintainer 2026-08-16: - removed manhole (1,060,111 downloads/month but last push 2024-07, past the 12-month activity line; also mis-homed under Tracing, it is an inspection socket not a tracer) - removed memory_graph (13,393 downloads/month, added 2025-12 by the project's own author with no displacement argued, teaching aid, fails the obvious-choice bar) - renamed python-hunter to hunter (PyPI package name is hunter; the python-hunter name on PyPI is a squatter) - reordered Others by downloads: django-debug-toolbar 9.1M, icecream 1.95M, flask-debugtoolbar 1.24M Co-Authored-By: Claude --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6ead29ff1a..1f4a25e334 100644 --- a/README.md +++ b/README.md @@ -649,16 +649,14 @@ _Libraries for debugging code._ - [ipdb](https://github.com/gotcha/ipdb) - IPython-enabled [pdb](https://docs.python.org/3/library/pdb.html). - [pudb](https://github.com/inducer/pudb) - A full-screen, console-based Python debugger. - Tracing - - [manhole](https://github.com/ionelmc/python-manhole) - Debugging UNIX socket connections and present the stacktraces for all threads and an interactive prompt. - - [python-hunter](https://github.com/ionelmc/python-hunter) - A flexible code tracing toolkit. + - [hunter](https://github.com/ionelmc/python-hunter) - A flexible code tracing toolkit. - Profiler - [py-spy](https://github.com/benfred/py-spy) - A sampling profiler for Python programs. Written in Rust. - [scalene](https://github.com/plasma-umass/scalene) - A high-performance, high-precision CPU, GPU, and memory profiler for Python. - Others - [django-debug-toolbar](https://github.com/django-commons/django-debug-toolbar) - Display various debug information for Django. - - [flask-debugtoolbar](https://github.com/pallets-eco/flask-debugtoolbar) - A port of the django-debug-toolbar to flask. - [icecream](https://github.com/gruns/icecream) - Inspect variables, expressions, and program execution with a single, simple function call. - - [memory_graph](https://github.com/bterwijn/memory_graph) - Visualize Python data at runtime to debug references, mutability, and aliasing. + - [flask-debugtoolbar](https://github.com/pallets-eco/flask-debugtoolbar) - A port of the django-debug-toolbar to flask. ### Build Tools From 3a65a020c4e01c3a8f244d2618fb6e4fdc6e9baa Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 11:54:56 +0800 Subject: [PATCH 072/168] feat: add memray to Profiler Bloomberg memory profiler that tracks allocations in Python code, native extensions, and the interpreter itself. 15.6M downloads/month via ClickPy; the obvious choice for memory profiling work per maintainer audit 2026-08-16. Ordered after py-spy (28.5M/month) per downloads-descending tier. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1f4a25e334..cce922e35b 100644 --- a/README.md +++ b/README.md @@ -652,6 +652,7 @@ _Libraries for debugging code._ - [hunter](https://github.com/ionelmc/python-hunter) - A flexible code tracing toolkit. - Profiler - [py-spy](https://github.com/benfred/py-spy) - A sampling profiler for Python programs. Written in Rust. + - [memray](https://github.com/bloomberg/memray) - A memory profiler that tracks allocations in Python code, native extensions, and the interpreter itself. - [scalene](https://github.com/plasma-umass/scalene) - A high-performance, high-precision CPU, GPU, and memory profiler for Python. - Others - [django-debug-toolbar](https://github.com/django-commons/django-debug-toolbar) - Display various debug information for Django. From d316a8ee2adfe6848e04da1bb7c6b12d7b705945 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 11:55:29 +0800 Subject: [PATCH 073/168] feat: add pyinstrument to Profiler Developer Tools audit adjudicated by maintainer 2026-08-16: obvious choice per ClickPy (10.6M downloads/month), a statistical wall-clock profiler and common first reach for request-level profiling. Ordered after memray (15.6M/month), before challenger scalene (400K/month). Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cce922e35b..a008185667 100644 --- a/README.md +++ b/README.md @@ -653,6 +653,7 @@ _Libraries for debugging code._ - Profiler - [py-spy](https://github.com/benfred/py-spy) - A sampling profiler for Python programs. Written in Rust. - [memray](https://github.com/bloomberg/memray) - A memory profiler that tracks allocations in Python code, native extensions, and the interpreter itself. + - [pyinstrument](https://github.com/joerick/pyinstrument) - A statistical wall-clock profiler with low overhead and readable call-tree output. - [scalene](https://github.com/plasma-umass/scalene) - A high-performance, high-precision CPU, GPU, and memory profiler for Python. - Others - [django-debug-toolbar](https://github.com/django-commons/django-debug-toolbar) - Display various debug information for Django. From 81256884939c25e32c53a4c5ea5869044a528cfe Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 11:56:08 +0800 Subject: [PATCH 074/168] audit: sweep Build Tools to the shortlist cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed bitbake (no PyPI distribution, ships with Yocto — its users are embedded-Linux developers, fails the Serves Python Developers scope test). Removed platformio (1,255,169 downloads/month — embedded and IoT toolchain written in Python but used for C and C++ firmware work, same scope test as bitbake). Removed pybuilder (51,511 downloads/month — searches confirm niche adoption, small community, fails the obvious-choice bar). Reordered remaining entries: invoke (85.4M) and scons (924K) as obvious choices, doit (803K) as challenger. Co-Authored-By: Claude --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index a008185667..c649ac800a 100644 --- a/README.md +++ b/README.md @@ -664,12 +664,9 @@ _Libraries for debugging code._ _Compile software from source code._ -- [bitbake](https://github.com/openembedded/bitbake) - A make-like build tool for embedded Linux. -- [doit](https://github.com/pydoit/doit) - A task runner and build tool. - [invoke](https://github.com/pyinvoke/invoke) - A tool for managing shell-oriented subprocesses and organizing executable Python code into CLI-invokable tasks. -- [platformio](https://github.com/platformio/platformio-core) - A console tool to build code with different development platforms. -- [pybuilder](https://github.com/pybuilder/pybuilder) - A continuous build tool written in pure Python. - [scons](https://github.com/SCons/scons) - A software construction tool. +- [doit](https://github.com/pydoit/doit) - A task runner and build tool. ### Documentation From 71eee5d240299b4e6a8a091525b22327f6e53a5f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 11:56:39 +0800 Subject: [PATCH 075/168] feat: add ipython to Interactive Interpreter Obvious choice per maintainer audit 2026-08-16: 175.7M downloads/month via ClickPy, the default enhanced REPL and the kernel under Jupyter, yet missing from the README. Placed first per downloads-descending obvious-choice tier (jupyter 17.5M follows). Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c649ac800a..d95c547504 100644 --- a/README.md +++ b/README.md @@ -574,6 +574,7 @@ _Python implementation of data structures, algorithms and design patterns. Also _Interactive Python interpreters (REPL)._ +- [ipython](https://github.com/ipython/ipython) - A powerful interactive Python shell, and the kernel behind Jupyter notebooks. - [jupyter](https://github.com/jupyter/notebook) - A rich toolkit to help you make the most out of using Python interactively. - [awesome-jupyter](https://github.com/markusschanta/awesome-jupyter) - [marimo](https://github.com/marimo-team/marimo) - Transform data and train models, feels like a next-gen notebook, stored as Git-friendly Python. From 2d0f5da2794083d1519e6ef64dc90bcc54b7c1a6 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 11:57:11 +0800 Subject: [PATCH 076/168] feat: add mkdocs-material as sub-item under mkdocs Adjudicated by maintainer 2026-08-16: mkdocs-material pulls 17.6M downloads/month via ClickPy, nearly equal to mkdocs itself, and is the theme most mkdocs sites run. Listed as a sub-item since its job is inseparable from its parent. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d95c547504..75e2cd4891 100644 --- a/README.md +++ b/README.md @@ -675,6 +675,7 @@ _Libraries for generating project documentation._ - [diagrams](https://github.com/mingrammer/diagrams) - Diagram as Code. - [mkdocs](https://github.com/mkdocs/mkdocs/) - Markdown friendly documentation generator. + - [mkdocs-material](https://github.com/squidfunk/mkdocs-material) - [pdoc](https://github.com/mitmproxy/pdoc) - Epydoc replacement to auto generate API documentation for Python libraries. - [sphinx](https://github.com/sphinx-doc/sphinx/) - Python Documentation generator. - [awesome-sphinxdoc](https://github.com/ygzgxyz/awesome-sphinxdoc) From 166c9c97df118522d83d587c1ed8d835db7b1f4e Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 11:57:52 +0800 Subject: [PATCH 077/168] style: reorder Algorithms and Design Patterns and Documentation by downloads Developer Tools audit adjudicated by maintainer 2026-08-16, format-only outcome for the two sections with no removals. Algorithms: sortedcontainers (278.7M/month) first, then educational no-signal repos algorithms and thealgorithms alphabetically. Design Patterns: transitions (2.9M/month) before no-signal python-patterns. Documentation: sphinx (85.9M), mkdocs (17.8M), diagrams (6.8M) as obvious choices, pdoc (2.1M) as challenger. Co-Authored-By: Claude --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 75e2cd4891..180682b8d3 100644 --- a/README.md +++ b/README.md @@ -563,12 +563,12 @@ _Libraries for quantum computing._ _Python implementation of data structures, algorithms and design patterns. Also see [awesome-algorithms](https://github.com/tayllan/awesome-algorithms)._ - Algorithms - - [algorithms](https://github.com/keon/algorithms) - Minimal examples of data structures and algorithms. - [sortedcontainers](https://github.com/grantjenks/python-sortedcontainers) - Fast and pure-Python implementation of sorted collections. + - [algorithms](https://github.com/keon/algorithms) - Minimal examples of data structures and algorithms. - [thealgorithms](https://github.com/TheAlgorithms/Python) - All Algorithms implemented in Python. - Design Patterns - - [python-patterns](https://github.com/faif/python-patterns) - A collection of design patterns in Python. - [transitions](https://github.com/pytransitions/transitions) - A lightweight, object-oriented finite state machine implementation. + - [python-patterns](https://github.com/faif/python-patterns) - A collection of design patterns in Python. ### Interactive Interpreter @@ -673,12 +673,12 @@ _Compile software from source code._ _Libraries for generating project documentation._ -- [diagrams](https://github.com/mingrammer/diagrams) - Diagram as Code. +- [sphinx](https://github.com/sphinx-doc/sphinx/) - Python Documentation generator. + - [awesome-sphinxdoc](https://github.com/ygzgxyz/awesome-sphinxdoc) - [mkdocs](https://github.com/mkdocs/mkdocs/) - Markdown friendly documentation generator. - [mkdocs-material](https://github.com/squidfunk/mkdocs-material) +- [diagrams](https://github.com/mingrammer/diagrams) - Diagram as Code. - [pdoc](https://github.com/mitmproxy/pdoc) - Epydoc replacement to auto generate API documentation for Python libraries. -- [sphinx](https://github.com/sphinx-doc/sphinx/) - Python Documentation generator. - - [awesome-sphinxdoc](https://github.com/ygzgxyz/awesome-sphinxdoc) **DevOps** From fb7383cd9b46ad623d28339bc52518eed183ac3c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 11:58:58 +0800 Subject: [PATCH 078/168] docs: point Build Tools readers to Package Management uv-build was deliberately not admitted to Build Tools since PEP 517 backends are a different job; that structure decision is deferred to the Python Toolchain sitting. Add a cross-reference so readers looking for Python packaging/build tooling (uv build backend, hatch) land on Package Management instead. Co-Authored-By: Claude --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 180682b8d3..62076ecda2 100644 --- a/README.md +++ b/README.md @@ -663,7 +663,7 @@ _Libraries for debugging code._ ### Build Tools -_Compile software from source code._ +_Compile software from source code. If you're looking for Python packaging/build tools, see [Package Management](#package-management)._ - [invoke](https://github.com/pyinvoke/invoke) - A tool for managing shell-oriented subprocesses and organizing executable Python code into CLI-invokable tasks. - [scons](https://github.com/SCons/scons) - A software construction tool. From a610fcec61598a0b1645118ac67bd11f2e312894 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:13:54 +0800 Subject: [PATCH 079/168] audit: sweep DevOps Tools to the shortlist cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit removed openstack (mirror-index repo aggregating OpenStack projects — nothing installable, not configuration management; its daily pushes are mirror automation) removed kubesdk (2,135 downloads/month, 105 stars, repo created 2025-10, entered via PR #3166 — nowhere near obvious choice or challenger; maintainer also declined adding the official docker and kubernetes clients, so no Containers use case) renamed cloudinit to cloud-init (repo name; not on PyPI), saltstack to salt (PyPI name; Broadcom-sponsored, kept as Second Tier challenger — PyPI 102K/month undercounts onedir and distro installs), sentry-python to sentry-sdk (PyPI name; 178.5M/month), borg to borgbackup (PyPI name; the bare borg package on PyPI is unrelated) reordered every subcategory by tier and downloads: Cloud Providers boto3 3.4B then awscli 264.3M; Configuration Management ansible 13.0M and no-signal cloud-init obvious choices, pyinfra 271K and salt challengers; Deployment fabric 12.7M then chalice 930K; Monitoring and Processes psutil 391.5M, sentry-sdk, supervisor 16.8M, challenger sh 12.0M; Other pre-commit 198.0M, borgbackup 76K, chaostoolkit 18K Co-Authored-By: Claude --- README.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 62076ecda2..cd6b14d74d 100644 --- a/README.md +++ b/README.md @@ -687,27 +687,25 @@ _Libraries for generating project documentation._ _Software and libraries for DevOps._ - Cloud Providers - - [awscli](https://github.com/aws/aws-cli) - Universal Command Line Interface for Amazon Web Services. - [boto3](https://github.com/boto/boto3) - Python interface to Amazon Web Services. + - [awscli](https://github.com/aws/aws-cli) - Universal Command Line Interface for Amazon Web Services. - Configuration Management - [ansible](https://github.com/ansible/ansible) - A radically simple IT automation platform. - - [cloudinit](https://github.com/canonical/cloud-init) - A multi-distribution package that handles early initialization of a cloud instance. - - [openstack](https://github.com/openstack/openstack) - Open source software for building private and public clouds. + - [cloud-init](https://github.com/canonical/cloud-init) - A multi-distribution package that handles early initialization of a cloud instance. - [pyinfra](https://github.com/pyinfra-dev/pyinfra) - A versatile CLI tools and python libraries to automate infrastructure. - - [saltstack](https://github.com/saltstack/salt) - Infrastructure automation and management system. + - [salt](https://github.com/saltstack/salt) - Infrastructure automation and management system. - Deployment - - [chalice](https://github.com/aws/chalice) - A Python serverless microframework for AWS. - [fabric](https://github.com/fabric/fabric) - A simple, Pythonic tool for remote execution and deployment. + - [chalice](https://github.com/aws/chalice) - A Python serverless microframework for AWS. - Monitoring and Processes - [psutil](https://github.com/giampaolo/psutil) - A cross-platform process and system utilities module. - - [sentry-python](https://github.com/getsentry/sentry-python) - Sentry SDK for Python. - - [sh](https://github.com/amoffat/sh) - A full-fledged subprocess replacement for Python. + - [sentry-sdk](https://github.com/getsentry/sentry-python) - Sentry SDK for Python. - [supervisor](https://github.com/Supervisor/supervisor) - Supervisor process control system for UNIX. + - [sh](https://github.com/amoffat/sh) - A full-fledged subprocess replacement for Python. - Other - - [borg](https://github.com/borgbackup/borg) - A deduplicating archiver with compression and encryption. - - [chaostoolkit](https://github.com/chaostoolkit/chaostoolkit) - A Chaos Engineering toolkit & Orchestration for Developers. - - [kubesdk](https://github.com/puzl-cloud/kubesdk) - A modern async-first Kubernetes client and API model generator. - [pre-commit](https://github.com/pre-commit/pre-commit) - A framework for managing and maintaining multi-language pre-commit hooks. + - [borgbackup](https://github.com/borgbackup/borg) - A deduplicating archiver with compression and encryption. + - [chaostoolkit](https://github.com/chaostoolkit/chaostoolkit) - A Chaos Engineering toolkit & Orchestration for Developers. ### Distributed Computing From b06104c97e3a23d9a6841ea2edc269511a176b51 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:14:25 +0800 Subject: [PATCH 080/168] feat: add azure-sdk-for-python to Cloud Providers DevOps audit adjudicated by maintainer 2026-08-16: obvious choice. Umbrella repo published as per-service packages, so no single download figure exists; azure-identity alone is 230.4M downloads/month. Repo-name entry used per the naming rule since there is no single pip name. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cd6b14d74d..6950daa234 100644 --- a/README.md +++ b/README.md @@ -689,6 +689,7 @@ _Software and libraries for DevOps._ - Cloud Providers - [boto3](https://github.com/boto/boto3) - Python interface to Amazon Web Services. - [awscli](https://github.com/aws/aws-cli) - Universal Command Line Interface for Amazon Web Services. + - [azure-sdk-for-python](https://github.com/Azure/azure-sdk-for-python) - Microsoft Azure SDK for Python, published as per-service packages. - Configuration Management - [ansible](https://github.com/ansible/ansible) - A radically simple IT automation platform. - [cloud-init](https://github.com/canonical/cloud-init) - A multi-distribution package that handles early initialization of a cloud instance. From 77e7b62d938291d43af935cff63814dbdb753a2f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:15:10 +0800 Subject: [PATCH 081/168] feat: add google-cloud-python to Cloud Providers DevOps audit adjudicated by maintainer 2026-08-16: obvious-choice umbrella repo published as per-service packages, so no single download figure applies (google-cloud-storage alone is 253.1M downloads/month). Repo-name entry per the naming rule, placed after azure-sdk-for-python per no-signal alphabetical ordering within tier. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6950daa234..eb054c54d2 100644 --- a/README.md +++ b/README.md @@ -690,6 +690,7 @@ _Software and libraries for DevOps._ - [boto3](https://github.com/boto/boto3) - Python interface to Amazon Web Services. - [awscli](https://github.com/aws/aws-cli) - Universal Command Line Interface for Amazon Web Services. - [azure-sdk-for-python](https://github.com/Azure/azure-sdk-for-python) - Microsoft Azure SDK for Python, published as per-service packages. + - [google-cloud-python](https://github.com/googleapis/google-cloud-python) - Google Cloud client libraries for Python, published as per-service packages. - Configuration Management - [ansible](https://github.com/ansible/ansible) - A radically simple IT automation platform. - [cloud-init](https://github.com/canonical/cloud-init) - A multi-distribution package that handles early initialization of a cloud instance. From 4fc32225a92b5de382f71551988cc4e072fb7642 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:15:51 +0800 Subject: [PATCH 082/168] audit: sweep Distributed Computing to the shortlist cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed luigi (1,546,263 downloads/month, repo active with a push 2026-07) — the drop is editorial: Spotify itself moved to Flyte, 2026 orchestration comparisons no longer name luigi, and the Workflow Orchestration slots in Job Schedulers go to airflow, prefect, dagster. Flattened the sole Batch Processing subcategory — the label added nothing, the section is a single use case. Reordered by tier and downloads: obvious choices ray 62.6M, pyspark 48.3M, dask 30.0M; challengers joblib 216.9M raw (scikit-learn-dependency-inflated, judgment call — raw count still sorts it first in tier) and mpi4py 1.0M (HPC standard, specific audience not small). Co-Authored-By: Claude --- README.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index eb054c54d2..72081921da 100644 --- a/README.md +++ b/README.md @@ -713,13 +713,11 @@ _Software and libraries for DevOps._ _Frameworks and libraries for Distributed Computing._ -- Batch Processing - - [dask](https://github.com/dask/dask) - A flexible parallel computing library for analytic computing. - - [luigi](https://github.com/spotify/luigi) - A module that helps you build complex pipelines of batch jobs. - - [mpi4py](https://github.com/mpi4py/mpi4py) - Python bindings for MPI. - - [pyspark](https://github.com/apache/spark) - [Apache Spark](https://spark.apache.org/) Python API. - - [joblib](https://github.com/joblib/joblib) - A set of tools to provide lightweight pipelining in Python. - - [ray](https://github.com/ray-project/ray/) - A system for parallel and distributed Python that unifies the machine learning ecosystem. +- [ray](https://github.com/ray-project/ray/) - A system for parallel and distributed Python that unifies the machine learning ecosystem. +- [pyspark](https://github.com/apache/spark) - [Apache Spark](https://spark.apache.org/) Python API. +- [dask](https://github.com/dask/dask) - A flexible parallel computing library for analytic computing. +- [joblib](https://github.com/joblib/joblib) - A set of tools to provide lightweight pipelining in Python. +- [mpi4py](https://github.com/mpi4py/mpi4py) - Python bindings for MPI. ### Task Queues From 83c723d61f45e796e6c120cbbdb3a0b22547e0bc Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:16:27 +0800 Subject: [PATCH 083/168] style: reorder Task Queues by tier and downloads DevOps audit adjudicated 2026-08-16, format-only (no removals). Obvious choices: celery 58.4M, rq 18.1M, dramatiq 1.6M (promoted -- 2026 sources call it the top celery alternative with closest feature parity). Challengers: huey 20.9M (demoted -- raw count highest but 2026 sources file it as the lightweight small-app option), taskiq 2.0M. flower sub-item rides celery. Co-Authored-By: Claude --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 72081921da..bf7e8ed586 100644 --- a/README.md +++ b/README.md @@ -725,9 +725,9 @@ _Libraries for working with task queues._ - [celery](https://github.com/celery/celery) - An asynchronous task queue/job queue based on distributed message passing. - [flower](https://github.com/mher/flower) +- [rq](https://github.com/rq/rq) - Simple job queues for Python. - [dramatiq](https://github.com/Bogdanp/dramatiq) - A fast and reliable background task processing library for Python 3. - [huey](https://github.com/coleifer/huey) - Little multi-threaded task queue. -- [rq](https://github.com/rq/rq) - Simple job queues for Python. - [taskiq](https://github.com/taskiq-python/taskiq) - Distributed task queue with native asyncio support and pluggable brokers. ### Messaging From e5ce98c0f2ef5297b47fa5dd6246a17a0cf30296 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:16:59 +0800 Subject: [PATCH 084/168] feat: add confluent-kafka to Messaging DevOps audit adjudicated by maintainer 2026-08-16: 61.8M downloads/month via ClickPy, librdkafka-backed, 2026 sources call it the production Kafka default. kafka-python is unmaintained and was excluded. Placed first per downloads-descending obvious-choice tier; pika and paho-mqtt follow in subsequent commits. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bf7e8ed586..fc0f2a70da 100644 --- a/README.md +++ b/README.md @@ -734,6 +734,7 @@ _Libraries for working with task queues._ _Libraries for working with message brokers and event streaming._ +- [confluent-kafka](https://github.com/confluentinc/confluent-kafka-python) - Confluent's Python client for Apache Kafka, built on librdkafka. - [faststream](https://github.com/ag2ai/faststream) - A framework for building asynchronous services over Apache Kafka, RabbitMQ, NATS, MQTT and Redis. ### Job Schedulers From 28b6d1398b4b597c5e5c3461dfe3e6a65738d540 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:17:28 +0800 Subject: [PATCH 085/168] feat: add pika to Messaging DevOps audit adjudicated by maintainer 2026-08-16: pika is the standard RabbitMQ/AMQP 0-9-1 client, 13.7M downloads/month via ClickPy. Ordered after confluent-kafka (61.8M/month) per downloads-descending tier. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fc0f2a70da..d2e574fc9d 100644 --- a/README.md +++ b/README.md @@ -735,6 +735,7 @@ _Libraries for working with task queues._ _Libraries for working with message brokers and event streaming._ - [confluent-kafka](https://github.com/confluentinc/confluent-kafka-python) - Confluent's Python client for Apache Kafka, built on librdkafka. +- [pika](https://github.com/pika/pika) - Pure-Python RabbitMQ/AMQP 0-9-1 client library. - [faststream](https://github.com/ag2ai/faststream) - A framework for building asynchronous services over Apache Kafka, RabbitMQ, NATS, MQTT and Redis. ### Job Schedulers From 7fd495730d4952574af9dcbcf5b008b0dfc55573 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:17:59 +0800 Subject: [PATCH 086/168] feat: add paho-mqtt to Messaging Obvious choice per DevOps audit adjudicated by maintainer 2026-08-16: 9.1M downloads/month via ClickPy, Eclipse Foundation client described by 2026 sources as the bedrock of MQTT in Python. Ordered after pika (13.7M/month), before challenger faststream (1.5M/month). Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d2e574fc9d..d4c766a7d6 100644 --- a/README.md +++ b/README.md @@ -736,6 +736,7 @@ _Libraries for working with message brokers and event streaming._ - [confluent-kafka](https://github.com/confluentinc/confluent-kafka-python) - Confluent's Python client for Apache Kafka, built on librdkafka. - [pika](https://github.com/pika/pika) - Pure-Python RabbitMQ/AMQP 0-9-1 client library. +- [paho-mqtt](https://github.com/eclipse-paho/paho.mqtt.python) - The Eclipse Paho MQTT client for Python. - [faststream](https://github.com/ag2ai/faststream) - A framework for building asynchronous services over Apache Kafka, RabbitMQ, NATS, MQTT and Redis. ### Job Schedulers From 03d9139c35b6ea94642f120437b1fcd20f954a78 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:18:40 +0800 Subject: [PATCH 087/168] audit: sweep Job Schedulers to the shortlist cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the flat section into two use cases — Task Scheduling (in-process scheduling) and Workflow Orchestration (data-pipeline orchestrators) — six entries were covering two distinct jobs. Removed SpiffWorkflow (59,736 downloads/month — BPMN engine, a different job than scheduling or orchestration, small audience; active repo, drop is a judgment call). Kept schedule by explicit maintainer override (9.4M downloads/month, 12.3K stars, but no commits since 2024-05 — past the 12-month activity line; the maintainer overrode the activity rule, schedule slots as challenger behind apscheduler). Renamed airflow to apache-airflow (PyPI name — the bare airflow package is a 38K/month shim). Ordering: Task Scheduling apscheduler 55.5M obvious choice then schedule 9.4M challenger; Workflow Orchestration obvious choices apache-airflow 20.9M, prefect 14.0M, dagster 10.2M. luigi's removal from Distributed Computing rode that section's commit; flytekit was proposed and declined. Co-Authored-By: Claude --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d4c766a7d6..1900fdcb96 100644 --- a/README.md +++ b/README.md @@ -743,12 +743,13 @@ _Libraries for working with message brokers and event streaming._ _Libraries for scheduling jobs._ -- [airflow](https://github.com/apache/airflow) - Airflow is a platform to programmatically author, schedule and monitor workflows. -- [apscheduler](https://github.com/agronholm/apscheduler) - A light but powerful in-process task scheduler that lets you schedule functions. -- [dagster](https://github.com/dagster-io/dagster) - An orchestration platform for the development, production, and observation of data assets. -- [prefect](https://github.com/PrefectHQ/prefect) - A modern workflow orchestration framework that makes it easy to build, schedule and monitor robust data pipelines. -- [schedule](https://github.com/dbader/schedule) - Python job scheduling for humans. -- [SpiffWorkflow](https://github.com/sartography/SpiffWorkflow) - A powerful workflow engine implemented in pure Python. +- Task Scheduling + - [apscheduler](https://github.com/agronholm/apscheduler) - A light but powerful in-process task scheduler that lets you schedule functions. + - [schedule](https://github.com/dbader/schedule) - Python job scheduling for humans. +- Workflow Orchestration + - [apache-airflow](https://github.com/apache/airflow) - Airflow is a platform to programmatically author, schedule and monitor workflows. + - [prefect](https://github.com/PrefectHQ/prefect) - A modern workflow orchestration framework that makes it easy to build, schedule and monitor robust data pipelines. + - [dagster](https://github.com/dagster-io/dagster) - An orchestration platform for the development, production, and observation of data assets. ### Logging From 635a73580264676893bbb88a1ce33e92dea9ecdb Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:19:12 +0800 Subject: [PATCH 088/168] audit: sweep Logging to the shortlist cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed logfmter (197,351 downloads/month, 107 stars) — logfmt formatting is a small audience and it is not a credible successor to any obvious choice; judgment call. Reordered by tier and downloads: obvious choices structlog 114.5M (2026 consensus production pick), loguru 82.5M (developer-experience pick), and stdlib logging last as a no-signal entry — kept because stdlib logging is itself the obvious choice for the use case, the stdlib rule's yes-case. Co-Authored-By: Claude --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1900fdcb96..ee584e5024 100644 --- a/README.md +++ b/README.md @@ -755,10 +755,9 @@ _Libraries for scheduling jobs._ _Libraries for generating and working with logs._ -- [logfmter](https://github.com/josheppinette/python-logfmter) - A standard library compatible logfmt formatter. -- [logging](https://docs.python.org/3/library/logging.html) - (Python standard library) Logging facility for Python. -- [loguru](https://github.com/Delgan/loguru) - Library which aims to bring enjoyable logging in Python. - [structlog](https://github.com/hynek/structlog) - Structured logging made easy. +- [loguru](https://github.com/Delgan/loguru) - Library which aims to bring enjoyable logging in Python. +- [logging](https://docs.python.org/3/library/logging.html) - (Python standard library) Logging facility for Python. ### Network Virtualization From b8cacb558c984f40c88d6646f130af41b34b0554 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:19:44 +0800 Subject: [PATCH 089/168] audit: sweep Network Virtualization to the shortlist cap Removed mininet: no commits since 2024-07, past the 12-month activity line; 2026 sources describe it as fading with forks carrying development; its 3.7K/month PyPI row is not its real distribution channel. Reordered remaining obvious choices by downloads: scapy 4.4M then napalm 199K. Section rename to Networking was offered and the maintainer left the current name standing. Co-Authored-By: Claude --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index ee584e5024..412aa51a7a 100644 --- a/README.md +++ b/README.md @@ -763,9 +763,8 @@ _Libraries for generating and working with logs._ _Tools and libraries for Virtual Networking and SDN (Software Defined Networking)._ -- [mininet](https://github.com/mininet/mininet) - A popular network emulator and API written in Python. -- [napalm](https://github.com/napalm-automation/napalm) - Cross-vendor API to manipulate network devices. - [scapy](https://github.com/secdev/scapy) - A brilliant packet manipulation library. +- [napalm](https://github.com/napalm-automation/napalm) - Cross-vendor API to manipulate network devices. **CLI & GUI** From 3290ce586a69e2e8164ad242e81457f45f5dd217 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:26:20 +0800 Subject: [PATCH 090/168] style: merge Security Linters into Linters and Formatters bandit (29.5M downloads/month) sorts last in the second tier behind pylint 65.2M and flake8 56.7M. The merged use case now holds 6 entries, past the hard cap of 5, by explicit maintainer override -- the list's first cap override, accepted knowingly. Co-Authored-By: Claude --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 412aa51a7a..6329333d9f 100644 --- a/README.md +++ b/README.md @@ -595,10 +595,9 @@ _Tools of static analysis, linters and code quality checkers. Also see [awesome- - [pylint](https://github.com/pylint-dev/pylint) - A fully customizable source code analyzer. - [flake8](https://github.com/PyCQA/flake8) - A wrapper around `pycodestyle`, `pyflakes` and McCabe. - [awesome-flake8-extensions](https://github.com/DmytroLitvinov/awesome-flake8-extensions) + - [bandit](https://github.com/PyCQA/bandit) - A tool designed to find common security issues in Python code. - Refactoring - [rope](https://github.com/python-rope/rope) - Rope is a python refactoring library. -- Security Linters - - [bandit](https://github.com/PyCQA/bandit) - A tool designed to find common security issues in Python code. - Type Checkers - [awesome-python-typing](https://github.com/typeddjango/awesome-python-typing) - [mypy](https://github.com/python/mypy) - Check variable types during compile time. - [typeshed](https://github.com/python/typeshed) From 35c68984e879a40e0480099c050805b82a5ec1f7 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:55:38 +0800 Subject: [PATCH 091/168] audit: sweep CLI Development, mint TUI Frameworks, drop cement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure: textual and asciimatics move from Terminal Rendering to a minted TUI Frameworks subcategory — full-screen terminal UIs are a distinct job from rendering output. urwid joins them in the GUI Development commit, which dissolves that section's Terminal subcategory. Renames to canonical PyPI names: python-prompt-toolkit → prompt_toolkit, python-fire → fire (the PyPI package named python-fire is an unrelated name-squatter; Google's project installs as fire). Tiers: click (1.12B/mo), typer (366M/mo), argparse (stdlib) obvious choices; prompt_toolkit (246.8M/mo), fire (22M/mo) challengers. tqdm (670.1M/mo), rich (626.7M/mo) obvious choices; colorama (425.6M/mo, largely pip-transitive traffic, superseded by rich for new code) demoted to challenger (Second Tier) beside alive-progress (3.7M/mo). textual (535.4M/mo) obvious choice of TUI Frameworks, asciimatics (177.5K/mo) challenger. Removed: - cement — 565K downloads/month but 1.3K stars after 17 years (CI-shaped count); alive yet no longer anyone's unprompted answer against click, typer, fire, or prompt_toolkit. Judgment call. Co-Authored-By: Claude --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6329333d9f..fd30546745 100644 --- a/README.md +++ b/README.md @@ -772,19 +772,19 @@ _Tools and libraries for Virtual Networking and SDN (Software Defined Networking _Libraries for building command-line applications._ - CLI Development - - [argparse](https://docs.python.org/3/library/argparse.html) - (Python standard library) Command-line option and argument parsing. - - [cement](https://github.com/datafolklabs/cement) - CLI Application Framework for Python. - [click](https://github.com/pallets/click/) - A package for creating beautiful command line interfaces in a composable way. - - [python-fire](https://github.com/google/python-fire) - A library for creating command line interfaces from absolutely any Python object. - - [python-prompt-toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit) - A library for building powerful interactive command lines. - [typer](https://github.com/fastapi/typer) - Modern CLI framework that uses Python type hints. Built on Click and Pydantic. + - [argparse](https://docs.python.org/3/library/argparse.html) - (Python standard library) Command-line option and argument parsing. + - [prompt_toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit) - A library for building powerful interactive command lines. + - [fire](https://github.com/google/python-fire) - A library for creating command line interfaces from absolutely any Python object. - Terminal Rendering - - [alive-progress](https://github.com/rsalmei/alive-progress) - A new kind of Progress Bar, with real-time throughput, eta and very cool animations. - - [asciimatics](https://github.com/peterbrittain/asciimatics) - A package to create full-screen text UIs (from interactive forms to ASCII animations). - - [colorama](https://github.com/tartley/colorama) - Cross-platform colored terminal text. + - [tqdm](https://github.com/tqdm/tqdm) - Fast, extensible progress bar for loops and CLI. - [rich](https://github.com/Textualize/rich) - Python library for rich text and beautiful formatting in the terminal. Also provides a great `RichHandler` log handler. + - [colorama](https://github.com/tartley/colorama) - Cross-platform colored terminal text. + - [alive-progress](https://github.com/rsalmei/alive-progress) - A new kind of Progress Bar, with real-time throughput, eta and very cool animations. +- TUI Frameworks - [textual](https://github.com/Textualize/textual) - A framework for building interactive user interfaces that run in the terminal and the browser. - - [tqdm](https://github.com/tqdm/tqdm) - Fast, extensible progress bar for loops and CLI. + - [asciimatics](https://github.com/peterbrittain/asciimatics) - A package to create full-screen text UIs (from interactive forms to ASCII animations). ### CLI Tools From 1a8e14c177563cf6d213ff4d74978c11fa3273e8 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:56:03 +0800 Subject: [PATCH 092/168] audit: sweep CLI Tools, dissolve Productivity Tools, drop thefuck, kaydet, doitlive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure: the Productivity Tools grab-bag dissolves into use cases — Project Scaffolding (cookiecutter 10.1M/mo obvious choice, copier 2.5M/mo challenger), Shells (xonsh 419.5K/mo), Downloaders (yt-dlp 17.7M/mo), Terminal Workflow (tmuxp 129.4K/mo). CLI Enhancements renames to Database CLIs (pgcli 636.6K/mo, mycli 124.9K/mo, litecli 74.2K/mo obvious choices; iredis 8.3K/mo challenger); HTTP Clients minted for httpie. httpie kept by explicit maintainer override of the 12-month activity line (repo dormant since 2024-12, last release 2024-11; 1.04M downloads/month) — second use of the schedule precedent. Removed: - thefuck — dormant since 2024-07, past the 12-month activity line; 7K downloads/month (most installs come from brew, not pip). - kaydet — 48 stars, 5.6K downloads/month; a personal diary tool nowhere near obvious-choice or challenger territory. - doitlive — 651 downloads/month against 3.6K stars; alive but effectively unused. Judgment call. Co-Authored-By: Claude --- README.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index fd30546745..8ac0e0bf59 100644 --- a/README.md +++ b/README.md @@ -788,23 +788,24 @@ _Libraries for building command-line applications._ ### CLI Tools -_Useful CLI-based tools for productivity._ +_Useful CLI-based tools._ -- Productivity Tools +- Database CLIs + - [pgcli](https://github.com/dbcli/pgcli) - PostgreSQL CLI with autocompletion and syntax highlighting. + - [mycli](https://github.com/dbcli/mycli) - MySQL CLI with autocompletion and syntax highlighting. + - [litecli](https://github.com/dbcli/litecli) - SQLite CLI with autocompletion and syntax highlighting. + - [iredis](https://github.com/laixintao/iredis) - Redis CLI with autocompletion and syntax highlighting. +- Downloaders + - [yt-dlp](https://github.com/yt-dlp/yt-dlp) - A command-line program to download videos from YouTube and other video sites, a fork of youtube-dl. +- HTTP Clients + - [httpie](https://github.com/httpie/cli) - A command line HTTP client, a user-friendly cURL replacement. +- Project Scaffolding - [cookiecutter](https://github.com/cookiecutter/cookiecutter) - A command-line utility that creates projects from cookiecutters (project templates). - [copier](https://github.com/copier-org/copier) - A library and command-line utility for rendering projects templates. - - [doitlive](https://github.com/sloria/doitlive) - A tool for live presentations in the terminal. - - [kaydet](https://github.com/miratcan/kaydet) - Queryable personal database and terminal diary with SQLite search, tags, metadata, and AI integration via MCP. - - [thefuck](https://github.com/nvbn/thefuck) - Correcting your previous console command. - - [tmuxp](https://github.com/tmux-python/tmuxp) - A [tmux](https://github.com/tmux/tmux) session manager. +- Shells - [xonsh](https://github.com/xonsh/xonsh/) - A Python-powered shell. Full-featured and cross-platform. - - [yt-dlp](https://github.com/yt-dlp/yt-dlp) - A command-line program to download videos from YouTube and other video sites, a fork of youtube-dl. -- CLI Enhancements - - [httpie](https://github.com/httpie/cli) - A command line HTTP client, a user-friendly cURL replacement. - - [iredis](https://github.com/laixintao/iredis) - Redis CLI with autocompletion and syntax highlighting. - - [litecli](https://github.com/dbcli/litecli) - SQLite CLI with autocompletion and syntax highlighting. - - [mycli](https://github.com/dbcli/mycli) - MySQL CLI with autocompletion and syntax highlighting. - - [pgcli](https://github.com/dbcli/pgcli) - PostgreSQL CLI with autocompletion and syntax highlighting. +- Terminal Workflow + - [tmuxp](https://github.com/tmux-python/tmuxp) - A [tmux](https://github.com/tmux/tmux) session manager. ### GUI Development From 9bbe1cf6d0b55f37a11e75113c861bed5999ccbb Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 12:56:44 +0800 Subject: [PATCH 093/168] audit: sweep GUI Development, split Desktop into Qt and Tkinter, drop enaml, buridan/ui, curses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure: the 12-entry Desktop use case splits — Qt (PySide6 3.9M/mo, PyQt6 2.7M/mo, co-obvious pair differing in licensing) and Tkinter (customtkinter 1.13M/mo, tkinter stdlib obvious choices; tkdesigner challenger, kept by maintainer decision) mint as subcategories; residual Desktop lands at cap with pygobject (607.6K/mo), wxPython (354.8K/mo), kivy (288.8K/mo) obvious choices and dearpygui (193.5K/mo), toga (12.9K/mo, BeeWare trajectory) challengers. Renames to canonical PyPI names: PyQt → PyQt6, pyside → PySide6 (the PyPI package named pyside is the dead Qt4-era PySide 1). Re-homes: urwid (11.3M/mo) moves to CLI Development > TUI Frameworks as a challenger and pyglet (2.9M/mo, windowing and multimedia for games) moves to Game Development, dissolving this section's Terminal subcategory. Web-based keeps pywebview (2.19M/mo), nicegui (1.2M/mo), flet (444.1K/mo) as obvious choices; gooey stays sole Wrappers entry. Removed: - enaml — 14.1K downloads/month, 1.6K stars after 13 years; a declarative Qt DSL nobody names unprompted. Judgment call. - buridan/ui — 248 stars, no PyPI package; a component-snippet collection for Reflex, not a GUI framework. Fails admission. - curses — standard-library rule: stdlib holds a slot only where it is itself the obvious choice, and for building TUIs that is textual. Co-Authored-By: Claude --- README.md | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 8ac0e0bf59..8d4be26969 100644 --- a/README.md +++ b/README.md @@ -784,6 +784,7 @@ _Libraries for building command-line applications._ - [alive-progress](https://github.com/rsalmei/alive-progress) - A new kind of Progress Bar, with real-time throughput, eta and very cool animations. - TUI Frameworks - [textual](https://github.com/Textualize/textual) - A framework for building interactive user interfaces that run in the terminal and the browser. + - [urwid](https://github.com/urwid/urwid) - A library for creating terminal GUI applications with strong support for widgets, events, rich colors, etc. - [asciimatics](https://github.com/peterbrittain/asciimatics) - A package to create full-screen text UIs (from interactive forms to ASCII animations). ### CLI Tools @@ -812,26 +813,22 @@ _Useful CLI-based tools._ _Libraries for working with graphical user interface applications._ - Desktop - - [customtkinter](https://github.com/tomschimansky/customtkinter) - A modern and customizable python UI-library based on Tkinter. - - [dearpygui](https://github.com/hoffstadt/DearPyGui) - A Simple GPU accelerated Python GUI framework - - [enaml](https://github.com/nucleic/enaml) - Creating beautiful user-interfaces with Declarative Syntax like QML. - - [kivy](https://github.com/kivy/kivy) - A library for creating NUI applications, running on Windows, Linux, Mac OS X, Android and iOS. - - [pyglet](https://github.com/pyglet/pyglet) - A cross-platform windowing and multimedia library for Python. - [pygobject](https://github.com/GNOME/pygobject) - Python Bindings for GLib/GObject/GIO/GTK+ (GTK+3). - - [PyQt](https://www.riverbankcomputing.com/static/Docs/PyQt6/) - Python bindings for the [Qt](https://www.qt.io/) cross-platform application and UI framework. - - [pyside](https://github.com/pyside/pyside-setup) - Qt for Python offers the official Python bindings for [Qt](https://www.qt.io/), this is same as PyQt but it's the official binding with different licensing. - - [tkdesigner](https://github.com/ParthJadhav/Tkinter-Designer) - Generates Tkinter interfaces from Figma designs using the Figma API. - - [tkinter](https://docs.python.org/3/library/tkinter.html) - (Python standard library) The standard Python interface to the Tcl/Tk GUI toolkit. - - [toga](https://github.com/beeware/toga) - A Python native, OS native GUI toolkit. - [wxPython](https://github.com/wxWidgets/Phoenix) - A blending of the wxWidgets C++ class library with the Python. + - [kivy](https://github.com/kivy/kivy) - A library for creating NUI applications, running on Windows, Linux, Mac OS X, Android and iOS. + - [dearpygui](https://github.com/hoffstadt/DearPyGui) - A Simple GPU accelerated Python GUI framework + - [toga](https://github.com/beeware/toga) - A Python native, OS native GUI toolkit. +- Qt + - [PySide6](https://github.com/pyside/pyside-setup) - Qt for Python offers the official Python bindings for [Qt](https://www.qt.io/), same as PyQt6 but it's the official binding with different licensing. + - [PyQt6](https://www.riverbankcomputing.com/static/Docs/PyQt6/) - Python bindings for the [Qt](https://www.qt.io/) cross-platform application and UI framework. +- Tkinter + - [customtkinter](https://github.com/tomschimansky/customtkinter) - A modern and customizable python UI-library based on Tkinter. + - [tkinter](https://docs.python.org/3/library/tkinter.html) - (Python standard library) The standard Python interface to the Tcl/Tk GUI toolkit. + - [tkdesigner](https://github.com/ParthJadhav/Tkinter-Designer) - Generates Tkinter interfaces from Figma designs using the Figma API. - Web-based - - [buridan/ui](https://github.com/LineIndent/ui) - Composable, themeable components designed for Reflex. Extend, override, and ship without fighting the framework. Open source. - - [flet](https://github.com/flet-dev/flet) - Cross-platform GUI framework for building modern apps in pure Python. - - [nicegui](https://github.com/zauberzeug/nicegui) - An easy-to-use, Python-based UI framework, which shows up in your web browser. - [pywebview](https://github.com/r0x0r/pywebview/) - A lightweight cross-platform native wrapper around a webview component. -- Terminal - - [curses](https://docs.python.org/3/library/curses.html) - (Python standard library) The built-in wrapper for [ncurses](https://www.gnu.org/software/ncurses/) used to create terminal GUI applications. - - [urwid](https://github.com/urwid/urwid) - A library for creating terminal GUI applications with strong support for widgets, events, rich colors, etc. + - [nicegui](https://github.com/zauberzeug/nicegui) - An easy-to-use, Python-based UI framework, which shows up in your web browser. + - [flet](https://github.com/flet-dev/flet) - Cross-platform GUI framework for building modern apps in pure Python. - Wrappers - [gooey](https://github.com/chriskiehl/Gooey) - Turn command line programs into a full GUI application with one line. @@ -961,6 +958,7 @@ _Awesome game development libraries._ - [panda3d](https://github.com/panda3d/panda3d) - 3D game engine developed by Disney. - [py-sdl2](https://github.com/py-sdl/py-sdl2) - A ctypes based wrapper for the SDL2 library. - [pygame](https://github.com/pygame/pygame) - Pygame is a set of Python modules designed for writing games. +- [pyglet](https://github.com/pyglet/pyglet) - A cross-platform windowing and multimedia library for Python. - [pyopengl](https://github.com/mcfletch/pyopengl) - Python ctypes bindings for OpenGL and it's related APIs. - [renpy](https://github.com/renpy/renpy) - A Visual Novel engine. From 41a1b4b0ae5ae80431848a3f84c46815e2720a44 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:13:57 +0800 Subject: [PATCH 094/168] audit: sweep Image Processing, split into use cases, drop pymatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure: the flat section splits into Barcodes and QR Codes (qrcode 30.1M/mo, python-barcode 3.4M/mo, both obvious choices — generating codes is a distinct job from manipulating images), General (pillow 552M/mo, scikit-image 28.5M/mo obvious choices; wand 1.4M/mo, pyvips 808.2K/mo challengers), and Image Serving (thumbor sole obvious choice — a deployed service, so its 22K/mo pip count under-measures use). Rename to canonical PyPI name: python-qrcode → qrcode. Removed: - pymatting — 3.3M downloads/month, but the traffic is transitive: rembg declares pymatting as a hard dependency (verified in rembg's PyPI metadata). A single-task alpha-matting library, 1.9K stars, quiet since 2026-04; not an obvious choice for image processing. Co-Authored-By: Claude --- README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8d4be26969..f1212e44cd 100644 --- a/README.md +++ b/README.md @@ -922,14 +922,16 @@ _Libraries for file manipulation._ _Libraries for manipulating images._ -- [pillow](https://github.com/python-pillow/Pillow) - Pillow is the friendly [PIL](https://www.pythonware.com/products/pil/) fork. -- [pymatting](https://github.com/pymatting/pymatting) - A library for alpha matting. -- [python-barcode](https://github.com/WhyNotHugo/python-barcode) - Create barcodes in Python with no extra dependencies. -- [python-qrcode](https://github.com/lincolnloop/python-qrcode) - A pure Python QR Code generator. -- [pyvips](https://github.com/libvips/pyvips) - A fast image processing library with low memory needs. -- [scikit-image](https://github.com/scikit-image/scikit-image) - A Python library for (scientific) image processing. -- [thumbor](https://github.com/thumbor/thumbor) - A smart imaging service. It enables on-demand crop, re-sizing and flipping of images. -- [wand](https://github.com/emcconville/wand) - Python bindings for [MagickWand](https://www.imagemagick.org/script/magick-wand.php), C API for ImageMagick. +- Barcodes and QR Codes + - [qrcode](https://github.com/lincolnloop/python-qrcode) - A pure Python QR Code generator. + - [python-barcode](https://github.com/WhyNotHugo/python-barcode) - Create barcodes in Python with no extra dependencies. +- General + - [pillow](https://github.com/python-pillow/Pillow) - Pillow is the friendly [PIL](https://www.pythonware.com/products/pil/) fork. + - [scikit-image](https://github.com/scikit-image/scikit-image) - A Python library for (scientific) image processing. + - [wand](https://github.com/emcconville/wand) - Python bindings for [MagickWand](https://www.imagemagick.org/script/magick-wand.php), C API for ImageMagick. + - [pyvips](https://github.com/libvips/pyvips) - A fast image processing library with low memory needs. +- Image Serving + - [thumbor](https://github.com/thumbor/thumbor) - A smart imaging service. It enables on-demand crop, re-sizing and flipping of images. ### Audio & Video Processing From 9970486a2aa6dce24ceb6ba300f7dd61599946f0 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:14:13 +0800 Subject: [PATCH 095/168] feat: add rembg to Image Processing > General MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer-requested during the Media audit, replacing dropped pymatting with the tool whose traffic pymatting was carrying: rembg is the obvious choice for background removal — 4.1M downloads/month direct (pepy), 24.3K stars, pushed 2026-08, active release train. Takes the open third obvious-choice slot in General (no displacement needed), ordering after pillow and scikit-image. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f1212e44cd..089a8be6af 100644 --- a/README.md +++ b/README.md @@ -928,6 +928,7 @@ _Libraries for manipulating images._ - General - [pillow](https://github.com/python-pillow/Pillow) - Pillow is the friendly [PIL](https://www.pythonware.com/products/pil/) fork. - [scikit-image](https://github.com/scikit-image/scikit-image) - A Python library for (scientific) image processing. + - [rembg](https://github.com/danielgatis/rembg) - A tool to remove image backgrounds. - [wand](https://github.com/emcconville/wand) - Python bindings for [MagickWand](https://www.imagemagick.org/script/magick-wand.php), C API for ImageMagick. - [pyvips](https://github.com/libvips/pyvips) - A fast image processing library with low memory needs. - Image Serving From 8f9c3884bf944146cb122b41af3302d4129e84d1 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:14:37 +0800 Subject: [PATCH 096/168] audit: sweep Audio & Video Processing, re-home TTS to Speech, drop birdnet, matchering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure: gtts and KittenTTS re-home to AI and Agents > Speech — TTS belongs with the speech models, not audio processing. gtts (3M/mo, a 2014 service wrapper, quiet since 2026-04) lands as Second Tier; kittentts (renamed to its canonical PyPI name, 15.3K stars within a year of creation, pip count 3.9K/mo under-measures model adoption) as challenger. Speech is now at exact cap (5/5) — future additions there require displacement. Audio keeps pydub (21.4M/mo) and librosa (11.7M/mo) as obvious choices. Video unchanged: moviepy (7M/mo) obvious choice, vidgear (25.3K/mo) challenger. Metadata reorders to tiers: mutagen (8.2M/mo) obvious choice; tinytag (5.2M/mo), beets (67.4K/mo, kept as challenger rather than minting a sole-entry subcategory — judgment call). Removed: - birdnet — 7.1K downloads/month, 1.7K stars; an applied bioacoustics tool with a genuinely small audience, not an audio-processing choice. Judgment call. - matchering — 16.1K downloads/month, 2.6K stars; a single-task automated-mastering tool with a small audience, no trajectory. Judgment call. Co-Authored-By: Claude --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 089a8be6af..051a7ce8ac 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,8 @@ _Libraries for building AI applications, LLM integrations, and autonomous agents - [openai-whisper](https://github.com/openai/whisper) - A general-purpose automatic speech recognition model trained on 680k hours of multilingual and multitask supervised data. - [funasr](https://github.com/modelscope/FunASR) - Industrial-grade speech recognition toolkit with 170x realtime speed, 50+ languages, speaker diarization, and emotion detection. - [vibevoice](https://github.com/microsoft/VibeVoice) - A family of open-source voice AI models from Microsoft for text-to-speech and long-form speech recognition. + - [gtts](https://github.com/pndurette/gTTS) - Python library and CLI tool for converting text to speech using Google Translate TTS. + - [kittentts](https://github.com/KittenML/KittenTTS) - Lightweight ONNX text-to-speech library with small CPU-friendly models. ### Deep Learning @@ -939,19 +941,15 @@ _Libraries for manipulating images._ _Libraries for manipulating audio, video, and their metadata._ - Audio - - [birdnet](https://github.com/birdnet-team/BirdNET-Analyzer) - Deep learning framework for acoustic species detection; identifies bird species from audio recordings using TensorFlow. - - [gtts](https://github.com/pndurette/gTTS) - Python library and CLI tool for converting text to speech using Google Translate TTS. - - [KittenTTS](https://github.com/KittenML/KittenTTS) - Lightweight ONNX text-to-speech library with small CPU-friendly models. - - [librosa](https://github.com/librosa/librosa) - Python library for audio and music analysis. - - [matchering](https://github.com/sergree/matchering) - A library for automated reference audio mastering. - [pydub](https://github.com/jiaaro/pydub) - Manipulate audio with a simple and easy high level interface. + - [librosa](https://github.com/librosa/librosa) - Python library for audio and music analysis. - Video - [moviepy](https://github.com/Zulko/moviepy) - A module for script-based movie editing with many formats, including animated GIFs. - [vidgear](https://github.com/abhiTronix/vidgear) - Most Powerful multi-threaded Video Processing framework. - Metadata - - [beets](https://github.com/beetbox/beets) - A music library manager and [MusicBrainz](https://musicbrainz.org/) tagger. - [mutagen](https://github.com/quodlibet/mutagen) - A Python module to handle audio metadata. - [tinytag](https://github.com/tinytag/tinytag) - A library for reading music meta data of MP3, OGG, FLAC and Wave files. + - [beets](https://github.com/beetbox/beets) - A music library manager and [MusicBrainz](https://musicbrainz.org/) tagger. ### Game Development From 3f391b34ba5a2e29dfea0a1fdd1f0b95d65cbb19 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:14:54 +0800 Subject: [PATCH 097/168] audit: sweep Game Development, split into use cases, drop py-sdl2, pyopengl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure: the flat section splits into 3D Engines (panda3d 189.3K/mo, sole obvious choice), Game Frameworks (pygame 3.07M/mo and pyglet 2.9M/mo obvious choices; arcade 85.3K/mo challenger — pygame-ce joins as a challenger in its own addition commit), and Visual Novels (renpy sole obvious choice — its 4/mo pip count is meaningless since Ren'Py ships as its own SDK; ecosystem verified: 8,000+ published works, release 8.5.3 in 2026-05). Removed: - py-sdl2 — 71.1K downloads/month (as PySDL2), 344 stars; low-level SDL bindings whose job pygame-ce and pyglet cover for this list's audience. Judgment call. - pyopengl — 5.3M downloads/month, likely transitive scientific-visualization traffic (judgment call, mechanism unverified), 415 stars; raw OpenGL bindings are not a game-development obvious choice. Co-Authored-By: Claude --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 051a7ce8ac..729f8d69c5 100644 --- a/README.md +++ b/README.md @@ -955,13 +955,14 @@ _Libraries for manipulating audio, video, and their metadata._ _Awesome game development libraries._ -- [arcade](https://github.com/pythonarcade/arcade) - Arcade is a modern Python framework for crafting games with compelling graphics and sound. -- [panda3d](https://github.com/panda3d/panda3d) - 3D game engine developed by Disney. -- [py-sdl2](https://github.com/py-sdl/py-sdl2) - A ctypes based wrapper for the SDL2 library. -- [pygame](https://github.com/pygame/pygame) - Pygame is a set of Python modules designed for writing games. -- [pyglet](https://github.com/pyglet/pyglet) - A cross-platform windowing and multimedia library for Python. -- [pyopengl](https://github.com/mcfletch/pyopengl) - Python ctypes bindings for OpenGL and it's related APIs. -- [renpy](https://github.com/renpy/renpy) - A Visual Novel engine. +- 3D Engines + - [panda3d](https://github.com/panda3d/panda3d) - 3D game engine developed by Disney. +- Game Frameworks + - [pygame](https://github.com/pygame/pygame) - Pygame is a set of Python modules designed for writing games. + - [pyglet](https://github.com/pyglet/pyglet) - A cross-platform windowing and multimedia library for Python. + - [arcade](https://github.com/pythonarcade/arcade) - Arcade is a modern Python framework for crafting games with compelling graphics and sound. +- Visual Novels + - [renpy](https://github.com/renpy/renpy) - A Visual Novel engine. **Python Language** From 8a3771e8955ff9d349e3c3fd594dd02b4ad62e7c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:15:08 +0800 Subject: [PATCH 098/168] feat: add pygame-ce to Game Development > Game Frameworks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Challenger to pygame: the community fork where long-time contributors now develop, a drop-in replacement (same import name), and community guidance for new projects favors it — adoption-trajectory evidence verified by web search. 642.5K downloads/month (pepy), 1.6K stars, created 2023, pushed 2026-08. Upstream pygame itself has been quiet since 2025-11. Slots into the open challenger position ahead of arcade (85.3K/mo). Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 729f8d69c5..abc9dcbc9d 100644 --- a/README.md +++ b/README.md @@ -960,6 +960,7 @@ _Awesome game development libraries._ - Game Frameworks - [pygame](https://github.com/pygame/pygame) - Pygame is a set of Python modules designed for writing games. - [pyglet](https://github.com/pyglet/pyglet) - A cross-platform windowing and multimedia library for Python. + - [pygame-ce](https://github.com/pygame-community/pygame-ce) - An actively developed drop-in replacement with new features and performance improvements ([pygame](https://github.com/pygame/pygame) fork). - [arcade](https://github.com/pythonarcade/arcade) - Arcade is a modern Python framework for crafting games with compelling graphics and sound. - Visual Novels - [renpy](https://github.com/renpy/renpy) - A Visual Novel engine. From 9fa72c1ee63dc16bc5a205302b1a8e9b8c5c4a2a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:29:23 +0800 Subject: [PATCH 099/168] audit: sweep Implementations, drop ironpython MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tiers: cpython, micropython, pypy obvious choices (all no-signal — distributed outside pip — so alphabetical); cython (130.3M/mo, kept here by judgment as a Python-superset compiler with no better home) and pyodide (no pip signal; distributed via CDN and npm) challengers. Removed: - ironpython — latest release v3.4.2 (2024-12) still implements Python 3.4-era language, a decade behind CPython (verified from the release feed; the repo itself is active, so this is not an activity-line drop). 2.8K stars. Not an obvious choice for any current job. Co-Authored-By: Claude --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index abc9dcbc9d..da17f36761 100644 --- a/README.md +++ b/README.md @@ -972,11 +972,10 @@ _Awesome game development libraries._ _Implementations of Python._ - [cpython](https://github.com/python/cpython) - Default, most widely used implementation of the Python programming language written in C. -- [cython](https://github.com/cython/cython) - Optimizing Static Compiler for Python. -- [ironpython](https://github.com/IronLanguages/ironpython3) - Implementation of the Python programming language written in C#. - [micropython](https://github.com/micropython/micropython) - A lean and efficient Python programming language implementation. -- [pyodide](https://github.com/pyodide/pyodide) - Python distribution for the browser and Node.js based on WebAssembly. - [pypy](https://github.com/pypy/pypy) - A very fast and compliant implementation of the Python language. +- [cython](https://github.com/cython/cython) - Optimizing Static Compiler for Python. +- [pyodide](https://github.com/pyodide/pyodide) - Python distribution for the browser and Node.js based on WebAssembly. ### Built-in Classes Enhancement From 6af6158287528e760e07f643174af02840a13d2b Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:29:44 +0800 Subject: [PATCH 100/168] audit: sweep Functional Programming, drop coconut MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tiers: more-itertools (339.9M/mo), toolz (62.9M/mo), functools (stdlib, the first stop for FP utilities; no-signal, sorts last) obvious choices; funcy (7.3M/mo) and returns (1.37M/mo, typed monads/Result trajectory) challengers. Removed: - coconut — 14.4K downloads/month, 4.3K stars; a compiled language variant rather than a library, and nobody's unprompted answer for functional Python. Judgment call. Co-Authored-By: Claude --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index da17f36761..3c8dfd81ba 100644 --- a/README.md +++ b/README.md @@ -990,12 +990,11 @@ _Libraries for enhancing Python built-in classes._ _Functional Programming with Python._ -- [coconut](https://github.com/evhub/coconut) - A variant of Python built for simple, elegant, Pythonic functional programming. +- [more-itertools](https://github.com/more-itertools/more-itertools) - More routines for operating on iterables, beyond `itertools`. +- [toolz](https://github.com/pytoolz/toolz) - A collection of functional utilities for iterators, functions, and dictionaries. Also available as [cytoolz](https://github.com/pytoolz/cytoolz/) for Cython-accelerated performance. - [functools](https://docs.python.org/3/library/functools.html) - (Python standard library) Higher-order functions and operations on callable objects. - [funcy](https://github.com/Suor/funcy) - A fancy and practical functional tools. -- [more-itertools](https://github.com/more-itertools/more-itertools) - More routines for operating on iterables, beyond `itertools`. - [returns](https://github.com/dry-python/returns) - A set of type-safe monads, transformers, and composition utilities. -- [toolz](https://github.com/pytoolz/toolz) - A collection of functional utilities for iterators, functions, and dictionaries. Also available as [cytoolz](https://github.com/pytoolz/cytoolz/) for Cython-accelerated performance. ### Asynchronous Programming From 19875cf356ce0a5e85d0c3c2087bf7bbf54cafdf Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:30:08 +0800 Subject: [PATCH 101/168] audit: sweep Asynchronous Programming, split into Async I/O and Parallelism MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure: the flat section splits — async I/O and process/pool parallelism are distinct jobs. Parallelism holds concurrent.futures and multiprocessing (both standard library, both obvious choices, no-signal so alphabetical). Async I/O tiers: anyio (1.07B/mo — heavily transitive via httpx and Starlette, but independently the production-recommended structured- concurrency layer), uvloop (267.7M/mo), asyncio (stdlib, no-signal, sorts last; awesome-asyncio sub-item rides along) obvious choices; trio (53.8M/mo), gevent (49.6M/mo), twisted (15.1M/mo) challengers — gevent and twisted kept as Second Tier by explicit maintainer decision, and the use case holds 6 entries by explicit maintainer cap override (the list's second, after Linters and Formatters; same 3 obvious choices + 3 challengers shape). No removals. Co-Authored-By: Claude --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3c8dfd81ba..737dc2af68 100644 --- a/README.md +++ b/README.md @@ -1000,15 +1000,17 @@ _Functional Programming with Python._ _Libraries for asynchronous, concurrent and parallel execution. Also see [awesome-asyncio](https://github.com/timofurrer/awesome-asyncio)._ -- [anyio](https://github.com/agronholm/anyio) - A high-level async concurrency and networking framework that works on top of asyncio or trio. -- [asyncio](https://docs.python.org/3/library/asyncio.html) - (Python standard library) Asynchronous I/O, event loop, coroutines and tasks. - - [awesome-asyncio](https://github.com/timofurrer/awesome-asyncio) -- [concurrent.futures](https://docs.python.org/3/library/concurrent.futures.html) - (Python standard library) A high-level interface for asynchronously executing callables. -- [gevent](https://github.com/gevent/gevent) - A coroutine-based Python networking library that uses [greenlet](https://github.com/python-greenlet/greenlet). -- [multiprocessing](https://docs.python.org/3/library/multiprocessing.html) - (Python standard library) Process-based parallelism. -- [trio](https://github.com/python-trio/trio) - A friendly library for async concurrency and I/O. -- [twisted](https://github.com/twisted/twisted) - An event-driven networking engine. -- [uvloop](https://github.com/MagicStack/uvloop) - Ultra fast asyncio event loop. +- Async I/O + - [anyio](https://github.com/agronholm/anyio) - A high-level async concurrency and networking framework that works on top of asyncio or trio. + - [uvloop](https://github.com/MagicStack/uvloop) - Ultra fast asyncio event loop. + - [asyncio](https://docs.python.org/3/library/asyncio.html) - (Python standard library) Asynchronous I/O, event loop, coroutines and tasks. + - [awesome-asyncio](https://github.com/timofurrer/awesome-asyncio) + - [trio](https://github.com/python-trio/trio) - A friendly library for async concurrency and I/O. + - [gevent](https://github.com/gevent/gevent) - A coroutine-based Python networking library that uses [greenlet](https://github.com/python-greenlet/greenlet). + - [twisted](https://github.com/twisted/twisted) - An event-driven networking engine. +- Parallelism + - [concurrent.futures](https://docs.python.org/3/library/concurrent.futures.html) - (Python standard library) A high-level interface for asynchronously executing callables. + - [multiprocessing](https://docs.python.org/3/library/multiprocessing.html) - (Python standard library) Process-based parallelism. ### Date and Time From 16077fc0e10ae23cbc4f6a98e0e7621d7e40d978 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:30:35 +0800 Subject: [PATCH 102/168] style: re-tier Built-in Classes Enhancement and Date and Time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No removals in either section — tier ordering and canonical-name renames only. Built-in Classes Enhancement: attrs (939M/mo), bidict (30.5M/mo) obvious choices; uuid-utils (81.2M/mo, challenger on judgment — the count is transitive-profile against 364 stars) and python-box (renamed from box, its canonical PyPI name; 6.9M/mo) challengers. Date and Time: python-dateutil (renamed from dateutil, its canonical PyPI name; 1.21B/mo), dateparser (46.4M/mo), zoneinfo (stdlib, the timezone answer since 3.9; no-signal, sorts last) obvious choices; pendulum (71.6M/mo, revived 2026-07 after a long slump — Second Tier-shaped) challenger. Co-Authored-By: Claude --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 737dc2af68..c2d4b44c9a 100644 --- a/README.md +++ b/README.md @@ -983,8 +983,8 @@ _Libraries for enhancing Python built-in classes._ - [attrs](https://github.com/python-attrs/attrs) - Replacement for `__init__`, `__eq__`, `__repr__`, etc. boilerplate in class definitions. - [bidict](https://github.com/jab/bidict) - Efficient, Pythonic bidirectional map data structures and related functionality. -- [box](https://github.com/cdgriffith/Box) - Python dictionaries with advanced dot notation access. - [uuid-utils](https://github.com/aminalaee/uuid-utils) - A fast, Rust-backed drop-in replacement for Python's built-in `uuid` module, supporting RFC 9562 (UUIDv6, UUIDv7, and UUIDv8). +- [python-box](https://github.com/cdgriffith/Box) - Python dictionaries with advanced dot notation access. ### Functional Programming @@ -1016,10 +1016,10 @@ _Libraries for asynchronous, concurrent and parallel execution. Also see [awesom _Libraries for working with dates and times._ +- [python-dateutil](https://github.com/dateutil/dateutil) - Extensions to the standard Python [datetime](https://docs.python.org/3/library/datetime.html) module. - [dateparser](https://github.com/scrapinghub/dateparser) - A Python parser for human-readable dates in dozens of languages. -- [dateutil](https://github.com/dateutil/dateutil) - Extensions to the standard Python [datetime](https://docs.python.org/3/library/datetime.html) module. -- [pendulum](https://github.com/python-pendulum/pendulum) - Python datetimes made easy. - [zoneinfo](https://docs.python.org/3/library/zoneinfo.html) - (Python standard library) IANA time zone support. Brings the [tz database](https://en.wikipedia.org/wiki/Tz_database) into Python. +- [pendulum](https://github.com/python-pendulum/pendulum) - Python datetimes made easy. **Python Toolchain** From c00094add64eb157d5991d443742f4e90d726b16 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:30:53 +0800 Subject: [PATCH 103/168] feat: add whenever to Date and Time Challenger with verified adoption trajectory: 9M downloads/month (pepy), 2.4K stars, pushed 2026-08. Rust-backed and type-safe, with published benchmarks 10-100x faster than Pendulum and Arrow and a DST-correctness design aimed at the incumbents' known pitfalls. Slots into the second challenger position after pendulum. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c2d4b44c9a..e3d4795cd3 100644 --- a/README.md +++ b/README.md @@ -1020,6 +1020,7 @@ _Libraries for working with dates and times._ - [dateparser](https://github.com/scrapinghub/dateparser) - A Python parser for human-readable dates in dozens of languages. - [zoneinfo](https://docs.python.org/3/library/zoneinfo.html) - (Python standard library) IANA time zone support. Brings the [tz database](https://en.wikipedia.org/wiki/Tz_database) into Python. - [pendulum](https://github.com/python-pendulum/pendulum) - Python datetimes made easy. +- [whenever](https://github.com/ariebovenberg/whenever) - A modern datetime library, type-safe and DST-safe, backed by Rust. **Python Toolchain** From 15c4064ee1b82eea482766f2644204ed9083b9aa Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:36:30 +0800 Subject: [PATCH 104/168] docs: amend Entry Ordering so standard-library modules sort first in tier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer rule change: built-ins lead their tier instead of sorting last with the other no-signal entries — a stdlib module that earns a slot is the default answer, so it reads first. Several stdlib modules in one tier stay alphabetical. Non-stdlib no-signal entries (agent skill packs, projects distributed outside PyPI) still sort last in tier. README reorder of already-audited sections follows in a style commit; unaudited sections pick the rule up at their own audit. Co-Authored-By: Claude --- CONTEXT.md | 2 +- CONTRIBUTING.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index c6deb3cc1c..dd2b6dd5eb 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -44,7 +44,7 @@ The only admission path into a full Use Case: the PR names the entry it replaces _Avoid_: One-in-one-out (informal alias) **Challenger**: -An entry (at most two per Use Case) that is not yet the Obvious Choice but is a credible successor to one. Marked by ordering, not description: within a Use Case, Obvious Choices are listed first, then Challengers, each tier by PyPI downloads/month descending (no-signal entries last in tier, alphabetically). Admission requires adoption-trajectory evidence, not popularity alone. +An entry (at most two per Use Case) that is not yet the Obvious Choice but is a credible successor to one. Marked by ordering, not description: within a Use Case, Obvious Choices are listed first, then Challengers, each tier by PyPI downloads/month descending (standard-library modules first in tier, other no-signal entries last in tier, alphabetically). Admission requires adoption-trajectory evidence, not popularity alone. _Avoid_: Rising Star (old lane name), Hidden Gem (old lane name — concept removed entirely) **Second Tier**: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c16c0a3bb9..bcdfd99409 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,7 +73,7 @@ Use the **PyPI package name** as the display name so developers can copy it dire ### Entry Ordering -Within a use case, the obvious choices are listed first, ordered by PyPI downloads per month from high to low; challengers follow, in the same order. Entries without a download signal (standard-library modules, agent skill packs) sort last within their tier, alphabetically. There is no marker in the entry text — position is the marker, so the last entries of a use case may be its challengers. +Within a use case, the obvious choices are listed first, ordered by PyPI downloads per month from high to low; challengers follow, in the same order. Standard-library modules sort first within their tier — built-ins lead — alphabetically when there are several. Other entries without a download signal (agent skill packs, projects distributed outside PyPI) sort last within their tier, alphabetically. There is no marker in the entry text — position is the marker, so the last entries of a use case may be its challengers. ## Changing the Structure From 05a9dd4ed573533a07d410a5b5181341a96f53c5 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:37:14 +0800 Subject: [PATCH 105/168] style: move standard-library entries to the top of their tiers Applies the amended Entry Ordering rule (stdlib first in tier) retroactively to all audited sections: sqlite3 (SQLite), mock (Mock), logging (Logging), tomllib (Data Formats), argparse (CLI Development), tkinter (Tkinter), functools (Functional Programming), asyncio with its awesome-asyncio sub-item (Async I/O), zoneinfo (Date and Time). Parallelism (concurrent.futures, multiprocessing) is an all-stdlib tier and stays alphabetical. Unaudited sections (difflib, mimetypes, pathlib, configparser) pick the rule up at their own audit. No entry additions or removals. Co-Authored-By: Claude --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index e3d4795cd3..2c70b99b05 100644 --- a/README.md +++ b/README.md @@ -405,8 +405,8 @@ _Libraries for connecting and operating databases._ - [psycopg](https://github.com/psycopg/psycopg) - The most popular PostgreSQL adapter for Python. - [asyncpg](https://github.com/MagicStack/asyncpg) - A fast PostgreSQL Database Client Library for Python/asyncio. - SQLite - [awesome-sqlite](https://github.com/planetopendata/awesome-sqlite) - - [sqlite-utils](https://github.com/simonw/sqlite-utils) - Python CLI utility and library for manipulating SQLite databases. - [sqlite3](https://docs.python.org/3/library/sqlite3.html) - (Python standard library) SQLite interface compliant with DB-API 2.0. + - [sqlite-utils](https://github.com/simonw/sqlite-utils) - Python CLI utility and library for manipulating SQLite databases. - ClickHouse - [clickhouse-connect](https://github.com/ClickHouse/clickhouse-connect) - The official ClickHouse client, with SQLAlchemy and Superset connectors. - [clickhouse-driver](https://github.com/mymarilyn/clickhouse-driver) - Python driver with native interface for ClickHouse. @@ -629,9 +629,9 @@ _Libraries for testing codebases and generating test data. Also see [awesome-pyt - API Testing - [schemathesis](https://github.com/schemathesis/schemathesis) - A tool for automatic property-based testing of web applications built with Open API / Swagger specifications. - Mock + - [mock](https://docs.python.org/3/library/unittest.mock.html) - (Python standard library) A mocking and patching library. - [responses](https://github.com/getsentry/responses) - A utility library for mocking out the requests Python library. - [freezegun](https://github.com/spulec/freezegun) - Travel through time by mocking the datetime module. - - [mock](https://docs.python.org/3/library/unittest.mock.html) - (Python standard library) A mocking and patching library. - [vcrpy](https://github.com/kevin1024/vcrpy) - Record and replay HTTP interactions on your tests. - [respx](https://github.com/lundberg/respx) - Mock HTTPX with awesome request patterns and response side effects. - Object Factories @@ -756,9 +756,9 @@ _Libraries for scheduling jobs._ _Libraries for generating and working with logs._ +- [logging](https://docs.python.org/3/library/logging.html) - (Python standard library) Logging facility for Python. - [structlog](https://github.com/hynek/structlog) - Structured logging made easy. - [loguru](https://github.com/Delgan/loguru) - Library which aims to bring enjoyable logging in Python. -- [logging](https://docs.python.org/3/library/logging.html) - (Python standard library) Logging facility for Python. ### Network Virtualization @@ -774,9 +774,9 @@ _Tools and libraries for Virtual Networking and SDN (Software Defined Networking _Libraries for building command-line applications._ - CLI Development + - [argparse](https://docs.python.org/3/library/argparse.html) - (Python standard library) Command-line option and argument parsing. - [click](https://github.com/pallets/click/) - A package for creating beautiful command line interfaces in a composable way. - [typer](https://github.com/fastapi/typer) - Modern CLI framework that uses Python type hints. Built on Click and Pydantic. - - [argparse](https://docs.python.org/3/library/argparse.html) - (Python standard library) Command-line option and argument parsing. - [prompt_toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit) - A library for building powerful interactive command lines. - [fire](https://github.com/google/python-fire) - A library for creating command line interfaces from absolutely any Python object. - Terminal Rendering @@ -824,8 +824,8 @@ _Libraries for working with graphical user interface applications._ - [PySide6](https://github.com/pyside/pyside-setup) - Qt for Python offers the official Python bindings for [Qt](https://www.qt.io/), same as PyQt6 but it's the official binding with different licensing. - [PyQt6](https://www.riverbankcomputing.com/static/Docs/PyQt6/) - Python bindings for the [Qt](https://www.qt.io/) cross-platform application and UI framework. - Tkinter - - [customtkinter](https://github.com/tomschimansky/customtkinter) - A modern and customizable python UI-library based on Tkinter. - [tkinter](https://docs.python.org/3/library/tkinter.html) - (Python standard library) The standard Python interface to the Tcl/Tk GUI toolkit. + - [customtkinter](https://github.com/tomschimansky/customtkinter) - A modern and customizable python UI-library based on Tkinter. - [tkdesigner](https://github.com/ParthJadhav/Tkinter-Designer) - Generates Tkinter interfaces from Figma designs using the Figma API. - Web-based - [pywebview](https://github.com/r0x0r/pywebview/) - A lightweight cross-platform native wrapper around a webview component. @@ -905,8 +905,8 @@ _Libraries for parsing and manipulating specific text formats._ - [markdown](https://github.com/Python-Markdown/markdown) - A Python implementation of John Gruber’s Markdown. - [mistune](https://github.com/lepture/mistune) - Fastest and full featured pure Python parsers of Markdown. - Data Formats - - [pyyaml](https://github.com/yaml/pyyaml) - YAML implementations for Python. - [tomllib](https://docs.python.org/3/library/tomllib.html) - (Python standard library) Parse TOML files. + - [pyyaml](https://github.com/yaml/pyyaml) - YAML implementations for Python. ### File Manipulation @@ -990,9 +990,9 @@ _Libraries for enhancing Python built-in classes._ _Functional Programming with Python._ +- [functools](https://docs.python.org/3/library/functools.html) - (Python standard library) Higher-order functions and operations on callable objects. - [more-itertools](https://github.com/more-itertools/more-itertools) - More routines for operating on iterables, beyond `itertools`. - [toolz](https://github.com/pytoolz/toolz) - A collection of functional utilities for iterators, functions, and dictionaries. Also available as [cytoolz](https://github.com/pytoolz/cytoolz/) for Cython-accelerated performance. -- [functools](https://docs.python.org/3/library/functools.html) - (Python standard library) Higher-order functions and operations on callable objects. - [funcy](https://github.com/Suor/funcy) - A fancy and practical functional tools. - [returns](https://github.com/dry-python/returns) - A set of type-safe monads, transformers, and composition utilities. @@ -1001,10 +1001,10 @@ _Functional Programming with Python._ _Libraries for asynchronous, concurrent and parallel execution. Also see [awesome-asyncio](https://github.com/timofurrer/awesome-asyncio)._ - Async I/O - - [anyio](https://github.com/agronholm/anyio) - A high-level async concurrency and networking framework that works on top of asyncio or trio. - - [uvloop](https://github.com/MagicStack/uvloop) - Ultra fast asyncio event loop. - [asyncio](https://docs.python.org/3/library/asyncio.html) - (Python standard library) Asynchronous I/O, event loop, coroutines and tasks. - [awesome-asyncio](https://github.com/timofurrer/awesome-asyncio) + - [anyio](https://github.com/agronholm/anyio) - A high-level async concurrency and networking framework that works on top of asyncio or trio. + - [uvloop](https://github.com/MagicStack/uvloop) - Ultra fast asyncio event loop. - [trio](https://github.com/python-trio/trio) - A friendly library for async concurrency and I/O. - [gevent](https://github.com/gevent/gevent) - A coroutine-based Python networking library that uses [greenlet](https://github.com/python-greenlet/greenlet). - [twisted](https://github.com/twisted/twisted) - An event-driven networking engine. @@ -1016,9 +1016,9 @@ _Libraries for asynchronous, concurrent and parallel execution. Also see [awesom _Libraries for working with dates and times._ +- [zoneinfo](https://docs.python.org/3/library/zoneinfo.html) - (Python standard library) IANA time zone support. Brings the [tz database](https://en.wikipedia.org/wiki/Tz_database) into Python. - [python-dateutil](https://github.com/dateutil/dateutil) - Extensions to the standard Python [datetime](https://docs.python.org/3/library/datetime.html) module. - [dateparser](https://github.com/scrapinghub/dateparser) - A Python parser for human-readable dates in dozens of languages. -- [zoneinfo](https://docs.python.org/3/library/zoneinfo.html) - (Python standard library) IANA time zone support. Brings the [tz database](https://en.wikipedia.org/wiki/Tz_database) into Python. - [pendulum](https://github.com/python-pendulum/pendulum) - Python datetimes made easy. - [whenever](https://github.com/ariebovenberg/whenever) - A modern datetime library, type-safe and DST-safe, backed by Rust. From 5f6f1f020e3104f3f45ed42ec7a66e4e5b514af3 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:38:22 +0800 Subject: [PATCH 106/168] docs: clarify that standard-library modules lead the use case outright MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer correction to the previous amendment: stdlib sorts at the top of the whole use case, not merely first within its tier. No README movement results — the stdlib admission rule (a standard-library module is listed only where it is itself the obvious choice) means every stdlib entry already sits in the first tier, so tier-top and use-case-top coincide; the rule text now states the intent directly. Co-Authored-By: Claude --- CONTEXT.md | 2 +- CONTRIBUTING.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index dd2b6dd5eb..d7fb6b5342 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -44,7 +44,7 @@ The only admission path into a full Use Case: the PR names the entry it replaces _Avoid_: One-in-one-out (informal alias) **Challenger**: -An entry (at most two per Use Case) that is not yet the Obvious Choice but is a credible successor to one. Marked by ordering, not description: within a Use Case, Obvious Choices are listed first, then Challengers, each tier by PyPI downloads/month descending (standard-library modules first in tier, other no-signal entries last in tier, alphabetically). Admission requires adoption-trajectory evidence, not popularity alone. +An entry (at most two per Use Case) that is not yet the Obvious Choice but is a credible successor to one. Marked by ordering, not description: within a Use Case, Obvious Choices are listed first, then Challengers, each tier by PyPI downloads/month descending (standard-library modules first in the Use Case outright — always Obvious Choices by the stdlib rule — other no-signal entries last in tier, alphabetically). Admission requires adoption-trajectory evidence, not popularity alone. _Avoid_: Rising Star (old lane name), Hidden Gem (old lane name — concept removed entirely) **Second Tier**: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bcdfd99409..281df0cd15 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,7 +29,7 @@ Hard maximum: 5 entries per use case. This is a qualitative bar first and a nume **Evidence**: admission is decided by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars. Judgment overrides the signal's known failure modes (CI-inflated counts, model releases consumed as weights rather than pip installs, large-but-specific audiences misread as "niche"). The maintainer's decision is final. -Looking for an exhaustive catalog instead? Follow the awesome-* lists linked under individual entries (for example awesome-python-testing) — they exist precisely so this list doesn't have to be one. +Looking for an exhaustive catalog instead? Follow the awesome-\* lists linked under individual entries (for example awesome-python-testing) — they exist precisely so this list doesn't have to be one. ## Entry Format Reference @@ -73,7 +73,7 @@ Use the **PyPI package name** as the display name so developers can copy it dire ### Entry Ordering -Within a use case, the obvious choices are listed first, ordered by PyPI downloads per month from high to low; challengers follow, in the same order. Standard-library modules sort first within their tier — built-ins lead — alphabetically when there are several. Other entries without a download signal (agent skill packs, projects distributed outside PyPI) sort last within their tier, alphabetically. There is no marker in the entry text — position is the marker, so the last entries of a use case may be its challengers. +Within a use case, the obvious choices are listed first, ordered by PyPI downloads per month from high to low; challengers follow, in the same order. Standard-library modules sort first in the use case — built-ins lead, before everything else — alphabetically when there are several. (This never conflicts with tier order: a standard-library module is only listed where it is itself the obvious choice, so it always belongs to the first tier.) Other entries without a download signal (agent skill packs, projects distributed outside PyPI) sort last within their tier, alphabetically. There is no marker in the entry text — position is the marker, so the last entries of a use case may be its challengers. ## Changing the Structure From a4eba37b1ff100f74b49e02091fb5adba39aa348 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:52:22 +0800 Subject: [PATCH 107/168] audit: sweep Environment Management, drop KillPy, pyenv-win becomes a sub-item MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tiers: virtualenv (545.7M/mo, much of it transitive via pip and tox), uv (194.1M/mo, dual-listed here and in Package Managers by maintainer acceptance), pyenv (no pip signal — distributed via git and brew; 45.0K stars) all obvious choices. pyenv-win converts to an indented sub-item under pyenv (the flower/celery companion pattern — its job is inseparable from its parent's), freeing a slot without losing the pointer. Removed: - KillPy — 124 stars, created 2025, 3.7K downloads/month; nowhere near obvious-choice or challenger territory. Co-Authored-By: Claude --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2c70b99b05..9794a8261c 100644 --- a/README.md +++ b/README.md @@ -1028,11 +1028,10 @@ _Libraries for working with dates and times._ _Libraries for Python version and virtual environment management._ -- [KillPy](https://github.com/Tlaloc-Es/killpy) - Analyze, detect, and clean unused Python environments and pipx packages. -- [pyenv](https://github.com/pyenv/pyenv) - Simple Python version management. -- [pyenv-win](https://github.com/pyenv-win/pyenv-win) - Pyenv for Windows. -- [uv](https://github.com/astral-sh/uv) - An extremely fast Python version, package and project manager, written in Rust. - [virtualenv](https://github.com/pypa/virtualenv) - A tool to create isolated Python environments. +- [uv](https://github.com/astral-sh/uv) - An extremely fast Python version, package and project manager, written in Rust. +- [pyenv](https://github.com/pyenv/pyenv) - Simple Python version management. + - [pyenv-win](https://github.com/pyenv-win/pyenv-win) ### Package Management From 1b51907189bacb85533b8bd74a2835ec5acaa538 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:52:39 +0800 Subject: [PATCH 108/168] audit: sweep Package Management, mint Package Managers subcategory, cap override to 6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure: the flat section becomes two subcategories — Package Managers (this commit) and Build Backends (entering next as three addition commits; the pyproject build-backend choice is a distinct job from installing packages). Package Managers tiers: pip (689.4M/mo), uv (194.1M/mo, the 2026 default recommendation for new projects), poetry (79M/mo) obvious choices; hatch (22.2M/mo — kept by explicit maintainer flip against the seeded drop), pipx (7.1M/mo, Second Tier — uv tool covers the job for uv users), conda (no pip signal, the data-science distribution standard; sorts last) challengers. The use case holds 6 entries by explicit maintainer cap override — the list's third, same 3 obvious choices + 3 challengers shape as Linters and Async I/O. No removals. Co-Authored-By: Claude --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9794a8261c..c7faa9118d 100644 --- a/README.md +++ b/README.md @@ -1037,12 +1037,13 @@ _Libraries for Python version and virtual environment management._ _Libraries for package and dependency management._ -- [conda](https://github.com/conda/conda/) - Cross-platform, Python-agnostic binary package manager. -- [hatch](https://github.com/pypa/hatch) - Modern, extensible Python project manager for environments, builds, and publishing. -- [pip](https://github.com/pypa/pip) - The package installer for Python. -- [pipx](https://github.com/pypa/pipx) - Install and Run Python Applications in Isolated Environments. Like `npx` in Node.js. -- [poetry](https://github.com/python-poetry/poetry) - Python dependency management and packaging made easy. -- [uv](https://github.com/astral-sh/uv) - An extremely fast Python version, package and project manager, written in Rust. +- Package Managers + - [pip](https://github.com/pypa/pip) - The package installer for Python. + - [uv](https://github.com/astral-sh/uv) - An extremely fast Python version, package and project manager, written in Rust. + - [poetry](https://github.com/python-poetry/poetry) - Python dependency management and packaging made easy. + - [hatch](https://github.com/pypa/hatch) - Modern, extensible Python project manager for environments, builds, and publishing. + - [pipx](https://github.com/pypa/pipx) - Install and Run Python Applications in Isolated Environments. Like `npx` in Node.js. + - [conda](https://github.com/conda/conda/) - Cross-platform, Python-agnostic binary package manager. ### Package Repositories From 1a36f7742603425022f4bad520169b40d1a2e97d Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:52:51 +0800 Subject: [PATCH 109/168] feat: add setuptools to Package Management > Build Backends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mints the Build Backends subcategory — the deferred agenda item from the Developer Tools sitting (2026-08-16), landing in its designated Python Toolchain slot. setuptools is the incumbent obvious choice: 1.51B downloads/month (pepy), half the ecosystem still builds with it, pushed 2026-08. Co-Authored-By: Claude --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c7faa9118d..65bc8d3de8 100644 --- a/README.md +++ b/README.md @@ -1044,6 +1044,8 @@ _Libraries for package and dependency management._ - [hatch](https://github.com/pypa/hatch) - Modern, extensible Python project manager for environments, builds, and publishing. - [pipx](https://github.com/pypa/pipx) - Install and Run Python Applications in Isolated Environments. Like `npx` in Node.js. - [conda](https://github.com/conda/conda/) - Cross-platform, Python-agnostic binary package manager. +- Build Backends + - [setuptools](https://github.com/pypa/setuptools) - The historical and still most widely used pyproject build backend. ### Package Repositories From 0ec6f492f48c2aedf919a87fbe28eef7f73bf96d Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:53:03 +0800 Subject: [PATCH 110/168] feat: add hatchling to Package Management > Build Backends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The modern default backend — PyPA docs and project templates reach for it: 507M downloads/month (pepy), pushed 2026-08. Obvious choice alongside setuptools; ordering after it by downloads. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 65bc8d3de8..bbc1a920b0 100644 --- a/README.md +++ b/README.md @@ -1046,6 +1046,7 @@ _Libraries for package and dependency management._ - [conda](https://github.com/conda/conda/) - Cross-platform, Python-agnostic binary package manager. - Build Backends - [setuptools](https://github.com/pypa/setuptools) - The historical and still most widely used pyproject build backend. + - [hatchling](https://github.com/pypa/hatch) - Modern, extensible build backend from the hatch project. ### Package Repositories From 947b93943abb16bd9ba1d1ea2b9d434068e2cfcd Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:53:17 +0800 Subject: [PATCH 111/168] feat: add uv-build to Package Management > Build Backends Challenger: uv's own backend at 26.5M downloads/month (pepy) within a year of release, riding uv's adoption trajectory. Deferred by the maintainer from the Developer Tools sitting; this closes that agenda item. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bbc1a920b0..490698df7b 100644 --- a/README.md +++ b/README.md @@ -1047,6 +1047,7 @@ _Libraries for package and dependency management._ - Build Backends - [setuptools](https://github.com/pypa/setuptools) - The historical and still most widely used pyproject build backend. - [hatchling](https://github.com/pypa/hatch) - Modern, extensible build backend from the hatch project. + - [uv-build](https://github.com/astral-sh/uv) - uv's fast, minimal build backend for pure-Python projects. ### Package Repositories From 9f9bd8db1fddd11c365c3263180f5b36cfad9d8f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:53:35 +0800 Subject: [PATCH 112/168] style: split Distribution into Executables and Obfuscation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer-directed restructure: instead of dropping pyarmor as mis-homed, an Obfuscation subcategory is minted for it (sole obvious choice — 501.5K/mo, 5.2K stars, pushed 2026-08); code obfuscation is a distinct job from building executables. Executables tiers: pyinstaller (13.1M/mo), Nuitka (512K/mo) obvious choices; shiv (487.3K/mo), cx-Freeze (221K/mo) challengers. No removals. Co-Authored-By: Claude --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 490698df7b..da004ba14e 100644 --- a/README.md +++ b/README.md @@ -1061,11 +1061,13 @@ _Local PyPI repository server and proxies._ _Libraries to create packaged executables for release distribution._ -- [cx-Freeze](https://github.com/marcelotduarte/cx_Freeze) - It is a Python tool that converts Python scripts into standalone executables and installers for Windows, macOS, and Linux. -- [Nuitka](https://github.com/Nuitka/Nuitka) - Compiles Python programs into high-performance standalone executables (cross-platform, supports all Python versions). -- [pyarmor](https://github.com/dashingsoft/pyarmor) - A tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts. -- [pyinstaller](https://github.com/pyinstaller/pyinstaller) - Converts Python programs into stand-alone executables (cross-platform). -- [shiv](https://github.com/linkedin/shiv) - A command line utility for building fully self-contained zipapps (PEP 441), but with all their dependencies included. +- Executables + - [pyinstaller](https://github.com/pyinstaller/pyinstaller) - Converts Python programs into stand-alone executables (cross-platform). + - [Nuitka](https://github.com/Nuitka/Nuitka) - Compiles Python programs into high-performance standalone executables (cross-platform, supports all Python versions). + - [shiv](https://github.com/linkedin/shiv) - A command line utility for building fully self-contained zipapps (PEP 441), but with all their dependencies included. + - [cx-Freeze](https://github.com/marcelotduarte/cx_Freeze) - It is a Python tool that converts Python scripts into standalone executables and installers for Windows, macOS, and Linux. +- Obfuscation + - [pyarmor](https://github.com/dashingsoft/pyarmor) - A tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts. ### Configuration Files From 5a8c062f6d4150222b8e6f5648f55b06fc63cf2d Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:53:51 +0800 Subject: [PATCH 113/168] audit: sweep Configuration Files, drop python-decouple MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tiers: configparser (stdlib, leads the use case under the stdlib-first ordering rule), python-dotenv (782.2M/mo) obvious choices — pydantic-settings joins them in its own addition commit; hydra-core (23.8M/mo — renamed from hydra to its canonical PyPI name; the cache's bare hydra row is an ancient unrelated package; link updated to hydra-ecosystem/hydra, where the facebookresearch repo now redirects, target verified by description) and dynaconf (6.8M/mo) challengers. Removed: - python-decouple — repo dormant since 2024-11, last release 3.8 in 2023-03, three and a half years past any release and past the 12-month activity line. 8.4M downloads/month, 3.0K stars. Displaced by pydantic-settings (495M/mo) entering next. Co-Authored-By: Claude --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index da004ba14e..25b7d63a47 100644 --- a/README.md +++ b/README.md @@ -1074,10 +1074,9 @@ _Libraries to create packaged executables for release distribution._ _Libraries for storing and parsing configuration options._ - [configparser](https://docs.python.org/3/library/configparser.html) - (Python standard library) INI file parser. -- [dynaconf](https://github.com/dynaconf/dynaconf) - Dynaconf is a configuration manager with plugins for Django, Flask and FastAPI. -- [hydra](https://github.com/facebookresearch/hydra) - Hydra is a framework for elegantly configuring complex applications. -- [python-decouple](https://github.com/HBNetwork/python-decouple) - Strict separation of settings from code. - [python-dotenv](https://github.com/theskumar/python-dotenv) - Reads key-value pairs from a `.env` file and sets them as environment variables. +- [hydra-core](https://github.com/hydra-ecosystem/hydra) - Hydra is a framework for elegantly configuring complex applications. +- [dynaconf](https://github.com/dynaconf/dynaconf) - Dynaconf is a configuration manager with plugins for Django, Flask and FastAPI. **Security** From ee0caca89253536ae4c08d2ba875017efa58c3da Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 13:54:05 +0800 Subject: [PATCH 114/168] feat: add pydantic-settings to Configuration Files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Displacement of the dropped python-decouple: same job — settings from environment variables and files — done with validation and types on the pydantic ecosystem's momentum. 495M downloads/month (pepy), pushed 2026-08. Obvious choice, ordering after python-dotenv. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 25b7d63a47..aac3ebfff2 100644 --- a/README.md +++ b/README.md @@ -1075,6 +1075,7 @@ _Libraries for storing and parsing configuration options._ - [configparser](https://docs.python.org/3/library/configparser.html) - (Python standard library) INI file parser. - [python-dotenv](https://github.com/theskumar/python-dotenv) - Reads key-value pairs from a `.env` file and sets them as environment variables. +- [pydantic-settings](https://github.com/pydantic/pydantic-settings) - Settings management using Pydantic models with validation, loading from environment variables and secrets files. - [hydra-core](https://github.com/hydra-ecosystem/hydra) - Hydra is a framework for elegantly configuring complex applications. - [dynaconf](https://github.com/dynaconf/dynaconf) - Dynaconf is a configuration manager with plugins for Django, Flask and FastAPI. From cf38a34ed4b1ea0994d700a92ce793dd2699e461 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:03:35 +0800 Subject: [PATCH 115/168] refactor: re-home pre-commit to Code Analysis > Git Hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer-adjudicated close of the standing flag from the Developer Tools sitting: pre-commit is developer-workflow tooling (a git-hook framework orchestrating linters), not ops — it leaves the DevOps Tools > Other grab-bag for a minted sole-entry Git Hooks subcategory in Code Analysis. Placement avoids stretching the Linters and Formatters cap override (already 6 by maintainer word). No additions or removals — a pure re-home. Co-Authored-By: Claude --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aac3ebfff2..c251b007d0 100644 --- a/README.md +++ b/README.md @@ -590,6 +590,8 @@ _Tools of static analysis, linters and code quality checkers. Also see [awesome- - [vulture](https://github.com/jendrikseipp/vulture) - A tool for finding and analyzing dead Python code. - [prospector](https://github.com/prospector-dev/prospector) - A tool to analyze Python code. - [repowise](https://github.com/repowise-dev/repowise) - Codebase intelligence that indexes repos into dependency graphs, git history, and auto-generated docs with dead code detection. +- Git Hooks + - [pre-commit](https://github.com/pre-commit/pre-commit) - A framework for managing and maintaining multi-language pre-commit hooks. - Linters and Formatters - [ruff](https://github.com/astral-sh/ruff) - An extremely fast Python linter and code formatter. - [black](https://github.com/psf/black) - The uncompromising Python code formatter. @@ -706,7 +708,6 @@ _Software and libraries for DevOps._ - [supervisor](https://github.com/Supervisor/supervisor) - Supervisor process control system for UNIX. - [sh](https://github.com/amoffat/sh) - A full-fledged subprocess replacement for Python. - Other - - [pre-commit](https://github.com/pre-commit/pre-commit) - A framework for managing and maintaining multi-language pre-commit hooks. - [borgbackup](https://github.com/borgbackup/borg) - A deduplicating archiver with compression and encryption. - [chaostoolkit](https://github.com/chaostoolkit/chaostoolkit) - A Chaos Engineering toolkit & Orchestration for Developers. From 283f1425b3d73ffd494edc80b4093d6536bf6a8e Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:03:50 +0800 Subject: [PATCH 116/168] style: fix display-name casing to canonical PyPI names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer-approved batch: gtts → gTTS, twisted → Twisted, cython → Cython, per the naming convention (display name = canonical PyPI package name, verified via the PyPI JSON API). All three were caught post-commit in earlier sittings and parked awaiting explicit word. Co-Authored-By: Claude --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c251b007d0..ff3302fe21 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ _Libraries for building AI applications, LLM integrations, and autonomous agents - [openai-whisper](https://github.com/openai/whisper) - A general-purpose automatic speech recognition model trained on 680k hours of multilingual and multitask supervised data. - [funasr](https://github.com/modelscope/FunASR) - Industrial-grade speech recognition toolkit with 170x realtime speed, 50+ languages, speaker diarization, and emotion detection. - [vibevoice](https://github.com/microsoft/VibeVoice) - A family of open-source voice AI models from Microsoft for text-to-speech and long-form speech recognition. - - [gtts](https://github.com/pndurette/gTTS) - Python library and CLI tool for converting text to speech using Google Translate TTS. + - [gTTS](https://github.com/pndurette/gTTS) - Python library and CLI tool for converting text to speech using Google Translate TTS. - [kittentts](https://github.com/KittenML/KittenTTS) - Lightweight ONNX text-to-speech library with small CPU-friendly models. ### Deep Learning @@ -975,7 +975,7 @@ _Implementations of Python._ - [cpython](https://github.com/python/cpython) - Default, most widely used implementation of the Python programming language written in C. - [micropython](https://github.com/micropython/micropython) - A lean and efficient Python programming language implementation. - [pypy](https://github.com/pypy/pypy) - A very fast and compliant implementation of the Python language. -- [cython](https://github.com/cython/cython) - Optimizing Static Compiler for Python. +- [Cython](https://github.com/cython/cython) - Optimizing Static Compiler for Python. - [pyodide](https://github.com/pyodide/pyodide) - Python distribution for the browser and Node.js based on WebAssembly. ### Built-in Classes Enhancement @@ -1008,7 +1008,7 @@ _Libraries for asynchronous, concurrent and parallel execution. Also see [awesom - [uvloop](https://github.com/MagicStack/uvloop) - Ultra fast asyncio event loop. - [trio](https://github.com/python-trio/trio) - A friendly library for async concurrency and I/O. - [gevent](https://github.com/gevent/gevent) - A coroutine-based Python networking library that uses [greenlet](https://github.com/python-greenlet/greenlet). - - [twisted](https://github.com/twisted/twisted) - An event-driven networking engine. + - [Twisted](https://github.com/twisted/twisted) - An event-driven networking engine. - Parallelism - [concurrent.futures](https://docs.python.org/3/library/concurrent.futures.html) - (Python standard library) A high-level interface for asynchronously executing callables. - [multiprocessing](https://docs.python.org/3/library/multiprocessing.html) - (Python standard library) Process-based parallelism. From 438881adba615fb738b48f43f06070fb4d4bd756 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:12:29 +0800 Subject: [PATCH 117/168] =?UTF-8?q?style:=20audit=20Cryptography=20and=20P?= =?UTF-8?q?enetration=20Testing=20=E2=80=94=20renames=20and=20re-tiers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No removals in either section. Cryptography: adds the missing italic section description; reorders to downloads — cryptography (1.48B/mo), pynacl (241.7M/mo), paramiko (155.4M/mo; SSH kept here as secure-protocols-adjacent rather than minting a sole-entry use case) — all obvious choices. Penetration Testing: tiers mitmproxy (10.8M/mo) and sqlmap (official PyPI package verified, 65.3K/mo under-measures git-based usage; 38.2K stars) obvious choices; sherlock-project (renamed from sherlock — the bare PyPI name is an unrelated distributed-lock library; 115.9K/mo, 89.6K stars) and social-engineer-toolkit (renamed from setoolkit — no PyPI package, so the naming convention falls back to the repository name; no download signal, judged by ecosystem standing) challengers. Co-Authored-By: Claude --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ff3302fe21..fa7ebfff75 100644 --- a/README.md +++ b/README.md @@ -1084,18 +1084,20 @@ _Libraries for storing and parsing configuration options._ ### Cryptography +_Libraries for cryptographic primitives and secure protocols._ + - [cryptography](https://github.com/pyca/cryptography) - A package designed to expose cryptographic primitives and recipes to Python developers. -- [paramiko](https://github.com/paramiko/paramiko) - The leading native Python SSHv2 protocol library. - [pynacl](https://github.com/pyca/pynacl) - Python binding to the Networking and Cryptography (NaCl) library. +- [paramiko](https://github.com/paramiko/paramiko) - The leading native Python SSHv2 protocol library. ### Penetration Testing _Frameworks and tools for penetration testing._ - [mitmproxy](https://github.com/mitmproxy/mitmproxy) - An interactive TLS-capable intercepting HTTP proxy for penetration testers and software developers. -- [setoolkit](https://github.com/trustedsec/social-engineer-toolkit) - A toolkit for social engineering. -- [sherlock](https://github.com/sherlock-project/sherlock) - Hunt down social media accounts by username across social networks. - [sqlmap](https://github.com/sqlmapproject/sqlmap) - Automatic SQL injection and database takeover tool. +- [sherlock-project](https://github.com/sherlock-project/sherlock) - Hunt down social media accounts by username across social networks. +- [social-engineer-toolkit](https://github.com/trustedsec/social-engineer-toolkit) - A toolkit for social engineering. ### Web Security From fe7006edccca554d9f3176b1d05e5121827aa7f6 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:12:46 +0800 Subject: [PATCH 118/168] feat: add pip-audit, minting the Supply Chain Security section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PyPA-official dependency vulnerability scanner: 30.9M downloads/month (pepy; largely CI traffic, which is the use case), 1.3K stars, pushed 2026-08. Verified 2026 guidance names it the free baseline over the older commercial safety. Sole obvious choice. This mints the reform's first new section — an explicit maintainer override of decision 18 (all minted use cases are subcategories), accepted in the audit preview. TOC line, heading, and description ride this commit per the Build Backends pattern; placed alphabetically in the Security group. Co-Authored-By: Claude --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index fa7ebfff75..f9c97614ba 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@ An opinionated guide to the best Python frameworks, libraries, tools, and resour - [Cryptography](#cryptography) - [Penetration Testing](#penetration-testing) +- [Supply Chain Security](#supply-chain-security) - [Web Security](#web-security) **Other** @@ -1099,6 +1100,12 @@ _Frameworks and tools for penetration testing._ - [sherlock-project](https://github.com/sherlock-project/sherlock) - Hunt down social media accounts by username across social networks. - [social-engineer-toolkit](https://github.com/trustedsec/social-engineer-toolkit) - A toolkit for social engineering. +### Supply Chain Security + +_Tools for auditing dependencies against known vulnerabilities._ + +- [pip-audit](https://github.com/pypa/pip-audit) - Audits Python environments and dependency trees for known vulnerabilities, using the PyPI Advisory Database and OSV. + ### Web Security _Libraries for application-layer web security._ From 913b380cc849a494dae369b159992acf9d3f3b51 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:15:21 +0800 Subject: [PATCH 119/168] feat: add uv audit to Supply Chain Security MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer-proposed during the Security sitting: uv's built-in vulnerability and malware scanning (announced 2026-06, OSV-backed, 4-10x faster than pip-audit on typical projects). Enters as a no-signal challenger behind pip-audit — not a package, so this is a subcommand pointer entry linking the CLI docs (httpx.URL precedent). Astral marks the feature preview/unstable; kept by explicit maintainer override of the production-ready quality bar — the first stability override. The description carries the preview label. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f9c97614ba..06654d94ef 100644 --- a/README.md +++ b/README.md @@ -1105,6 +1105,7 @@ _Frameworks and tools for penetration testing._ _Tools for auditing dependencies against known vulnerabilities._ - [pip-audit](https://github.com/pypa/pip-audit) - Audits Python environments and dependency trees for known vulnerabilities, using the PyPI Advisory Database and OSV. +- [uv audit](https://docs.astral.sh/uv/reference/cli/#uv-audit) - uv's built-in dependency vulnerability and malware scanning backed by OSV (preview). ### Web Security From 16e17d62baca49c292bb1de7027d9c5cc75750ea Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:15:42 +0800 Subject: [PATCH 120/168] style: drop the preview label from uv audit's description Maintainer word: no preview marker in the entry text. The stability override itself stands unchanged. Co-Authored-By: Claude --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06654d94ef..263e21d3fe 100644 --- a/README.md +++ b/README.md @@ -1105,7 +1105,7 @@ _Frameworks and tools for penetration testing._ _Tools for auditing dependencies against known vulnerabilities._ - [pip-audit](https://github.com/pypa/pip-audit) - Audits Python environments and dependency trees for known vulnerabilities, using the PyPI Advisory Database and OSV. -- [uv audit](https://docs.astral.sh/uv/reference/cli/#uv-audit) - uv's built-in dependency vulnerability and malware scanning backed by OSV (preview). +- [uv audit](https://docs.astral.sh/uv/reference/cli/#uv-audit) - uv's built-in dependency vulnerability and malware scanning backed by OSV. ### Web Security From 0194cbbe13a0eb0f1da2a920f14f8f7bdcfd6998 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:26:42 +0800 Subject: [PATCH 121/168] audit: sweep Hardware, drop synology-api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tiers: bleak (2.5M/mo) and pynput (2.2M/mo) obvious choices; jumpstarter (1.5K/mo, 211 stars, created 2026-01) kept as a challenger by explicit maintainer flip against the seeded drop. Removed: - synology-api — 579 stars, 14.5K downloads/month; a single-vendor NAS API wrapper, not an obvious choice for any hardware job a general reader has. Judgment call. Co-Authored-By: Claude --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 263e21d3fe..375f11e170 100644 --- a/README.md +++ b/README.md @@ -1120,9 +1120,8 @@ _Libraries for application-layer web security._ _Libraries for programming with hardware._ - [bleak](https://github.com/hbldh/bleak) - A cross platform Bluetooth Low Energy Client for Python using asyncio. -- [jumpstarter](https://github.com/jumpstarter-dev/jumpstarter) - A hardware-in-the-loop testing framework with a Python client library for automated testing on real and virtual hardware. - [pynput](https://github.com/moses-palmer/pynput) - A library to control and monitor input devices. -- [synology-api](https://github.com/N4S4/synology-api) - Python wrapper for Synology NAS APIs: Surveillance Station, File Station, Download Station, Docker, and 50+ other endpoints. +- [jumpstarter](https://github.com/jumpstarter-dev/jumpstarter) - A hardware-in-the-loop testing framework with a Python client library for automated testing on real and virtual hardware. ### Microsoft Windows From f8e594a9b4b14d640ce10ee4de7acf88541136a1 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:27:02 +0800 Subject: [PATCH 122/168] audit: sweep Miscellaneous, drop tryton, re-home itsdangerous to Cryptography MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure: itsdangerous moves to Security > Cryptography as a challenger — HMAC-based data signing fits "cryptographic primitives and secure protocols" better than the grab-bag. Kept past the 12-month activity line (repo quiet since 2025-06, last release 2024-04) as mature-stable on the sortedcontainers precedent: 222.8M downloads/month, the signing answer, no successor. Miscellaneous keeps blinker (192.2M/mo) and boltons (26.5M/mo) as obvious choices. Removed: - tryton — 10.9K downloads/month, and that PyPI package is the desktop client (the framework server is trytond); the linked GitHub repo is a self-described 216-star mirror; and the ERP obvious choice by adoption is Odoo (~7M users vs hundreds-to-thousands of Tryton deployments, web-verified), which enters in the next commit. Co-Authored-By: Claude --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 375f11e170..b7ce34d272 100644 --- a/README.md +++ b/README.md @@ -1090,6 +1090,7 @@ _Libraries for cryptographic primitives and secure protocols._ - [cryptography](https://github.com/pyca/cryptography) - A package designed to expose cryptographic primitives and recipes to Python developers. - [pynacl](https://github.com/pyca/pynacl) - Python binding to the Networking and Cryptography (NaCl) library. - [paramiko](https://github.com/paramiko/paramiko) - The leading native Python SSHv2 protocol library. +- [itsdangerous](https://github.com/pallets/itsdangerous) - Various helpers to pass trusted data to untrusted environments. ### Penetration Testing @@ -1137,8 +1138,6 @@ _Useful libraries or tools that don't fit in the categories above._ - [blinker](https://github.com/pallets-eco/blinker) - A fast Python in-process signal/event dispatching system. - [boltons](https://github.com/mahmoud/boltons) - A set of pure-Python utilities. -- [itsdangerous](https://github.com/pallets/itsdangerous) - Various helpers to pass trusted data to untrusted environments. -- [tryton](https://github.com/tryton/tryton) - A general-purpose business framework. ## Resources From a2659635af676dbb7485b9a89487523a1b0ba25a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:27:23 +0800 Subject: [PATCH 123/168] feat: add odoo, minting the ERP section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Python ERP by adoption: about 7M users across editions, 50+ app modules, 53.7K stars, pushed daily (web-verified). Not pip-distributed — the PyPI odoo package is a dateless placeholder — so no download signal; judged by ecosystem and displayed by repository name (renpy precedent). Sole obvious choice. Second structure override of decision 18 by maintainer word (Supply Chain Security precedent): ERP lands as a new section in the Other group rather than a slot in the Miscellaneous grab-bag, replacing the dropped tryton. TOC line, heading, and description ride this commit. Co-Authored-By: Claude --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index b7ce34d272..bbcf23f03f 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ An opinionated guide to the best Python frameworks, libraries, tools, and resour **Other** +- [ERP](#erp) - [Hardware](#hardware) - [Microsoft Windows](#microsoft-windows) - [Miscellaneous](#miscellaneous) @@ -1116,6 +1117,12 @@ _Libraries for application-layer web security._ **Other** +### ERP + +_Enterprise resource planning frameworks._ + +- [odoo](https://github.com/odoo/odoo) - A suite of open source business apps: CRM, e-commerce, accounting, inventory, and thousands of community modules. + ### Hardware _Libraries for programming with hardware._ From 660d74623728db1610fefba83aee7f48f0469a79 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:30:54 +0800 Subject: [PATCH 124/168] style: move the ERP section to the Web Development group MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer challenge upheld: Odoo is a ready-made web application platform you extend, the sibling concept of CMS and Admin Panels — so the section belongs beside them, not in the Other grab-bag (its first placement was inertia from tryton's Miscellaneous home). TOC and body both move; the group's section tail stays alphabetical (Admin Panels, CMS, ERP, Static Site Generators). Co-Authored-By: Claude --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index bbcf23f03f..d40980d1f5 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ An opinionated guide to the best Python frameworks, libraries, tools, and resour - [Authentication](#authentication) - [Admin Panels](#admin-panels) - [CMS](#cms) +- [ERP](#erp) - [Static Site Generators](#static-site-generators) **HTTP & Scraping** @@ -121,7 +122,6 @@ An opinionated guide to the best Python frameworks, libraries, tools, and resour **Other** -- [ERP](#erp) - [Hardware](#hardware) - [Microsoft Windows](#microsoft-windows) - [Miscellaneous](#miscellaneous) @@ -338,6 +338,12 @@ _Content Management Systems._ - [wagtail](https://github.com/wagtail/wagtail) - A Django content management system. - [django-cms](https://github.com/django-cms/django-cms) - The easy-to-use and developer-friendly enterprise CMS powered by Django. +### ERP + +_Enterprise resource planning frameworks._ + +- [odoo](https://github.com/odoo/odoo) - A suite of open source business apps: CRM, e-commerce, accounting, inventory, and thousands of community modules. + ### Static Site Generators _Static site generator is a software that takes some text + templates as input and produces HTML files on the output._ @@ -1117,12 +1123,6 @@ _Libraries for application-layer web security._ **Other** -### ERP - -_Enterprise resource planning frameworks._ - -- [odoo](https://github.com/odoo/odoo) - A suite of open source business apps: CRM, e-commerce, accounting, inventory, and thousands of community modules. - ### Hardware _Libraries for programming with hardware._ From 34c550b8645b60f23847dabaa8c4d1a49ce96e71 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:47:44 +0800 Subject: [PATCH 125/168] style: split Deep Learning into Frameworks and Reinforcement Learning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No removals. Frameworks tiers: pytorch (96.6M/mo as PyPI torch — the display name stays pytorch by explicit maintainer word, a deliberate exception to the naming convention; the bare pytorch PyPI package is a squatting placeholder), tensorflow (19.2M/mo — production incumbent, flagged as a Second Tier demotion candidate for the next audit), keras (18.6M/mo, backend-agnostic since Keras 3) obvious choices; jax (21.8M/mo, TPU/performance trajectory) and pytorch-lightning (11M/mo) challengers. Landscape verified: PyTorch is the 2026 default with 85% research share. stable-baselines3 moves into the minted Reinforcement Learning subcategory — RL is a distinct job; gymnasium joins it next commit. Co-Authored-By: Claude --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d40980d1f5..7969498c39 100644 --- a/README.md +++ b/README.md @@ -177,12 +177,14 @@ _Libraries for building AI applications, LLM integrations, and autonomous agents _Frameworks for Neural Networks and Deep Learning. Also see [awesome-deep-learning](https://github.com/ChristosChristofidis/awesome-deep-learning)._ -- [jax](https://github.com/jax-ml/jax) - A library for high-performance numerical computing with automatic differentiation and JIT compilation. -- [keras](https://github.com/keras-team/keras) - A high-level deep learning library with support for JAX, TensorFlow, and PyTorch backends. -- [pytorch](https://github.com/pytorch/pytorch) - Tensors and Dynamic neural networks in Python with strong GPU acceleration. -- [pytorch-lightning](https://github.com/Lightning-AI/pytorch-lightning) - Deep learning framework to train, deploy, and ship AI products Lightning fast. -- [stable-baselines3](https://github.com/DLR-RM/stable-baselines3) - PyTorch implementations of Stable Baselines (deep) reinforcement learning algorithms. -- [tensorflow](https://github.com/tensorflow/tensorflow) - The most popular Deep Learning framework created by Google. +- Frameworks + - [pytorch](https://github.com/pytorch/pytorch) - Tensors and Dynamic neural networks in Python with strong GPU acceleration. + - [tensorflow](https://github.com/tensorflow/tensorflow) - The most popular Deep Learning framework created by Google. + - [keras](https://github.com/keras-team/keras) - A high-level deep learning library with support for JAX, TensorFlow, and PyTorch backends. + - [jax](https://github.com/jax-ml/jax) - A library for high-performance numerical computing with automatic differentiation and JIT compilation. + - [pytorch-lightning](https://github.com/Lightning-AI/pytorch-lightning) - Deep learning framework to train, deploy, and ship AI products Lightning fast. +- Reinforcement Learning + - [stable-baselines3](https://github.com/DLR-RM/stable-baselines3) - PyTorch implementations of Stable Baselines (deep) reinforcement learning algorithms. ### Machine Learning From b95ce7e9955b0b558ae82861ec22a0c5c431ec5c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:47:56 +0800 Subject: [PATCH 126/168] feat: add gymnasium to Deep Learning > Reinforcement Learning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RL environments standard: community successor to OpenAI Gym (unmaintained since 2022; few maintained RL libraries still support old Gym — web-verified). 6.5M downloads/month (pepy), 12.3K stars, pushed 2026-08. Obvious choice beside stable-baselines3, ordering first by downloads. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7969498c39..add6a1f446 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,7 @@ _Frameworks for Neural Networks and Deep Learning. Also see [awesome-deep-learni - [jax](https://github.com/jax-ml/jax) - A library for high-performance numerical computing with automatic differentiation and JIT compilation. - [pytorch-lightning](https://github.com/Lightning-AI/pytorch-lightning) - Deep learning framework to train, deploy, and ship AI products Lightning fast. - Reinforcement Learning + - [gymnasium](https://github.com/Farama-Foundation/Gymnasium) - A standard API for reinforcement learning environments with popular reference environments ([gym](https://github.com/openai/gym) successor). - [stable-baselines3](https://github.com/DLR-RM/stable-baselines3) - PyTorch implementations of Stable Baselines (deep) reinforcement learning algorithms. ### Machine Learning From 7d1c5c8d0083f6ed23bdff7f00ed8ca24a7c3cc6 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:48:21 +0800 Subject: [PATCH 127/168] audit: sweep Machine Learning, three-way split, drop h2o, mindsdb, scikit-lego, TabGAN, spark.ml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure: the 12-entry flat section splits into General (scikit-learn 234.7M/mo obvious choice; pgmpy 843.7K/mo and feature-engine — renamed from feature_engine to its canonical PyPI name, 297.1K/mo — challengers), Gradient Boosting (xgboost 52M/mo, lightgbm 26.5M/mo, catboost 6.3M/mo, all obvious choices; lightgbm's lightgbm-org link verified current — microsoft/LightGBM redirects there), and Time Series Forecasting (timesfm sole — a foundation model judged by ecosystem adoption, 285K/mo and 27.6K stars; prophet and darts are named absences, deliberately not added this sitting). Removed: - h2o — 215.1K downloads/month, 7.5K stars, and the repo is active; the drop is purely editorial: no longer anyone's unprompted answer against scikit-learn and the boosting trio. Judgment call. - mindsdb — the linked repo redirects to mindsdb/mindshub, a "models workspace"; the AI-layer-for-databases product this entry described no longer exists (verified). 23.9K downloads/month. - scikit-lego — 72.5K downloads/month, 1.4K stars; a grab-bag of sklearn extras that never became an unprompted answer. Judgment. - TabGAN — 574 stars, 2.3K downloads/month. Nowhere near the bar. - spark.ml — duplicate in all but name: pyspark is already listed in the audited DevOps group, same repo, same pip install. Structural. Co-Authored-By: Claude --- README.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index add6a1f446..1cc12b1dd7 100644 --- a/README.md +++ b/README.md @@ -191,18 +191,16 @@ _Frameworks for Neural Networks and Deep Learning. Also see [awesome-deep-learni _Libraries for Machine Learning. Also see [awesome-machine-learning](https://github.com/josephmisiti/awesome-machine-learning#python)._ -- [catboost](https://github.com/catboost/catboost) - A fast, scalable, high performance gradient boosting on decision trees library. -- [feature_engine](https://github.com/feature-engine/feature_engine) - sklearn compatible API with the widest toolset for feature engineering and selection. -- [h2o](https://github.com/h2oai/h2o-3) - Open Source Fast Scalable Machine Learning Platform. -- [lightgbm](https://github.com/lightgbm-org/LightGBM) - A fast, distributed, high performance gradient boosting framework. -- [mindsdb](https://github.com/mindsdb/minds) - MindsDB is an open source AI layer for existing databases that allows you to effortlessly develop, train and deploy state-of-the-art machine learning models using standard queries. -- [pgmpy](https://github.com/pgmpy/pgmpy) - A Python library for probabilistic graphical models and Bayesian networks. -- [scikit-learn](https://github.com/scikit-learn/scikit-learn) - The most popular Python library for Machine Learning with extensive documentation and community support. -- [scikit-lego](https://github.com/koaning/scikit-lego) - A collection of lego bricks for scikit-learn pipelines. -- [spark.ml](https://github.com/apache/spark) - [Apache Spark](https://spark.apache.org/)'s scalable [Machine Learning library](https://spark.apache.org/docs/latest/ml-guide.html) for distributed computing. -- [TabGAN](https://github.com/Diyago/Tabular-data-generation) - Synthetic tabular data generation using GANs, Diffusion Models, and LLMs. -- [timesfm](https://github.com/google-research/timesfm) - A pretrained foundation model from Google Research for time-series forecasting. -- [xgboost](https://github.com/dmlc/xgboost) - A scalable, portable, and distributed gradient boosting library. +- General + - [scikit-learn](https://github.com/scikit-learn/scikit-learn) - The most popular Python library for Machine Learning with extensive documentation and community support. + - [pgmpy](https://github.com/pgmpy/pgmpy) - A Python library for probabilistic graphical models and Bayesian networks. + - [feature-engine](https://github.com/feature-engine/feature_engine) - sklearn compatible API with the widest toolset for feature engineering and selection. +- Gradient Boosting + - [xgboost](https://github.com/dmlc/xgboost) - A scalable, portable, and distributed gradient boosting library. + - [lightgbm](https://github.com/lightgbm-org/LightGBM) - A fast, distributed, high performance gradient boosting framework. + - [catboost](https://github.com/catboost/catboost) - A fast, scalable, high performance gradient boosting on decision trees library. +- Time Series Forecasting + - [timesfm](https://github.com/google-research/timesfm) - A pretrained foundation model from Google Research for time-series forecasting. ### Natural Language Processing From c83b98c37e6c90d9ad2aae1cd2524c5222d3ec15 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:48:38 +0800 Subject: [PATCH 128/168] audit: sweep Natural Language Processing, drop funnlp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit General tiers: nltk (71.4M/mo), spacy (25.4M/mo) obvious choices; gensim (6M/mo, quiet since 2025-11 — watch) and stanza (1.1M/mo) challengers. Chinese: jieba kept as mature-stable past the 12-month activity line (repo quiet since 2024-08, last release 0.42.1 in 2020-01) on the sortedcontainers precedent — the fourth such keep: 3.3M downloads/month, 35.1K stars, still the Chinese segmentation answer with no successor. Removed: - funnlp — three independent grounds: a link-collection rather than a library; repo quiet since 2024-05, past the 12-month line; 55 downloads/month. Its 82.5K stars measure the bookmark, not a tool. Co-Authored-By: Claude --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 1cc12b1dd7..00163f100a 100644 --- a/README.md +++ b/README.md @@ -207,12 +207,11 @@ _Libraries for Machine Learning. Also see [awesome-machine-learning](https://git _Libraries for working with human languages._ - General - - [gensim](https://github.com/piskvorky/gensim) - Topic Modeling for Humans. - [nltk](https://github.com/nltk/nltk) - A leading platform for building Python programs to work with human language data. - [spacy](https://github.com/explosion/spaCy) - A library for industrial-strength natural language processing in Python and Cython. + - [gensim](https://github.com/piskvorky/gensim) - Topic Modeling for Humans. - [stanza](https://github.com/stanfordnlp/stanza) - The Stanford NLP Group's official Python library, supporting 60+ languages. - Chinese - - [funnlp](https://github.com/fighting41love/funNLP) - A collection of tools and datasets for Chinese NLP. - [jieba](https://github.com/fxsjy/jieba) - The most popular Chinese text segmentation library. ### Computer Vision From 67c9f7ae93bcd56b3ddf6c0e0eb58d9d09c7667f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 14:48:57 +0800 Subject: [PATCH 129/168] style: split Computer Vision into General and OCR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No removals. General tiers: opencv-python (renamed from opencv to the canonical pip package this entry already linked; 55.9M/mo) and ultralytics (8.4M/mo, 60.7K stars) obvious choices; kornia (3.1M/mo) and fiftyone (253.7K/mo — dataset tooling rather than a vision algorithm library, kept as the unprompted answer for that adjacent job) challengers. OCR minted as a distinct job: pytesseract (24M/mo) and easyocr (3.6M/mo, quiet since 2025-12 — watch) obvious choices. Co-Authored-By: Claude --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 00163f100a..089fa010c5 100644 --- a/README.md +++ b/README.md @@ -218,12 +218,14 @@ _Libraries for working with human languages._ _Libraries for Computer Vision._ -- [easyocr](https://github.com/JaidedAI/EasyOCR) - Ready-to-use OCR with 40+ languages supported. -- [fiftyone](https://github.com/voxel51/fiftyone) - The open-source tool for building high-quality datasets and computer vision models. -- [kornia](https://github.com/kornia/kornia/) - Open Source Differentiable Computer Vision Library for PyTorch. -- [opencv](https://github.com/opencv/opencv-python) - Open Source Computer Vision Library. -- [pytesseract](https://github.com/madmaze/pytesseract) - A wrapper for [Google Tesseract OCR](https://github.com/tesseract-ocr). -- [ultralytics](https://github.com/ultralytics/ultralytics) - Ultralytics YOLO for object detection, segmentation, pose estimation, and classification with state-of-the-art accuracy and speed. +- General + - [opencv-python](https://github.com/opencv/opencv-python) - Open Source Computer Vision Library. + - [ultralytics](https://github.com/ultralytics/ultralytics) - Ultralytics YOLO for object detection, segmentation, pose estimation, and classification with state-of-the-art accuracy and speed. + - [kornia](https://github.com/kornia/kornia/) - Open Source Differentiable Computer Vision Library for PyTorch. + - [fiftyone](https://github.com/voxel51/fiftyone) - The open-source tool for building high-quality datasets and computer vision models. +- OCR + - [pytesseract](https://github.com/madmaze/pytesseract) - A wrapper for [Google Tesseract OCR](https://github.com/tesseract-ocr). + - [easyocr](https://github.com/JaidedAI/EasyOCR) - Ready-to-use OCR with 40+ languages supported. ### Recommender Systems From da4383a06f71431ccc2d053059b0d262073c6833 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:09:02 +0800 Subject: [PATCH 130/168] audit: sweep Text Processing, dissolve General, drop textdistance, nameparser, user-agents, tree-sitter-language-pack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure: the 10-entry General grab-bag dissolves — Encoding and Unicode (chardet 224.1M/mo obvious choice, joined by charset-normalizer next commit; ftfy 14.4M/mo kept as the fifth mature-stable past-line keep, repo and release both 2024-10), Internationalization (babel 135.2M/mo sole), Transliteration and Slugs (python-slugify 87.7M/mo, unidecode 31.8M/mo), and a residual General (difflib stdlib-first, pyfiglet 6.2M/mo judgment keep). pypinyin (1.9M/mo) and pangu.py (14.9K/mo as PyPI pangu — display name kept by explicit maintainer word, the second deliberate naming exception after pytorch; kept on sole-tool judgment for CJK spacing) re-home to Natural Language Processing > Chinese as challengers beside jieba. Parser re-tiers: pygments (1.25B/mo), pyparsing (422.3M/mo), sqlparse (146.8M/mo) obvious choices; phonenumbers (renamed from python-phonenumbers, 39.4M/mo) and parsy (4M/mo) challengers. Unique identifiers reorders to shortuuid then sqids. Removed: - textdistance — last release 2024-07 (25 months) and repo quiet since 2025-04, past the 12-month line; displaced by rapidfuzz (181.7M/mo vs 2.5M), entering in its own commit. - python-nameparser — 3.3M downloads/month (as nameparser) and an active repo; editorial drop at cap: the domain-parser class is trimmed to the giant, phonenumbers. Judgment call. - python-user-agents — repo quiet since 2023-02, three and a half years past the 12-month line. - tree-sitter-language-pack — coordinated multi-entry self-promotion (automatic-rejection rule): PyPI provenance verified to xberg-io, the org that previously planted xberg and liter-llm. 6.6M/mo is real but the rule stands; its sibling drops from HTML Manipulation. Co-Authored-By: Claude --- README.md | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 089fa010c5..dc936e314e 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,8 @@ _Libraries for working with human languages._ - [stanza](https://github.com/stanfordnlp/stanza) - The Stanford NLP Group's official Python library, supporting 60+ languages. - Chinese - [jieba](https://github.com/fxsjy/jieba) - The most popular Chinese text segmentation library. + - [pypinyin](https://github.com/mozillazg/python-pinyin) - Convert Chinese hanzi (漢字) to pinyin (拼音). + - [pangu.py](https://github.com/vinta/pangu.py) - Paranoid text spacing. ### Computer Vision @@ -851,29 +853,26 @@ _Libraries for working with graphical user interface applications._ _Libraries for parsing and manipulating plain texts._ -- General - - [babel](https://github.com/python-babel/babel) - An internationalization library for Python. +- Encoding and Unicode - [chardet](https://github.com/chardet/chardet) - Python character encoding detector. - - [difflib](https://docs.python.org/3/library/difflib.html) - (Python standard library) Helpers for computing deltas. - [ftfy](https://github.com/rspeer/python-ftfy) - Makes Unicode text less broken and more consistent automagically. - - [pangu.py](https://github.com/vinta/pangu.py) - Paranoid text spacing. +- General + - [difflib](https://docs.python.org/3/library/difflib.html) - (Python standard library) Helpers for computing deltas. - [pyfiglet](https://github.com/pwaller/pyfiglet) - An implementation of figlet written in Python. - - [pypinyin](https://github.com/mozillazg/python-pinyin) - Convert Chinese hanzi (漢字) to pinyin (拼音). - - [python-slugify](https://github.com/un33k/python-slugify) - A Python slugify library that translates unicode to ASCII. - - [textdistance](https://github.com/life4/textdistance) - Compute distance between sequences with 30+ algorithms. - - [unidecode](https://github.com/avian2/unidecode) - ASCII transliterations of Unicode text. -- Unique identifiers - - [sqids](https://github.com/sqids/sqids-python) - A library for generating short unique IDs from numbers. - - [shortuuid](https://github.com/skorokithakis/shortuuid) - A generator library for concise, unambiguous and URL-safe UUIDs. +- Internationalization + - [babel](https://github.com/python-babel/babel) - An internationalization library for Python. - Parser - - [parsy](https://github.com/python-parsy/parsy) - Easy, generic parser combinator library for creating parsers. - [pygments](https://github.com/pygments/pygments) - A generic syntax highlighter. - [pyparsing](https://github.com/pyparsing/pyparsing) - A general purpose framework for generating parsers. - - [python-nameparser](https://github.com/derek73/python-nameparser) - Parsing human names into their individual components. - - [python-phonenumbers](https://github.com/daviddrysdale/python-phonenumbers) - Parsing, formatting, storing and validating international phone numbers. - - [python-user-agents](https://github.com/selwin/python-user-agents) - Browser user agent parser. - [sqlparse](https://github.com/andialbrecht/sqlparse) - A non-validating SQL parser. - - [tree-sitter-language-pack](https://github.com/xberg-io/tree-sitter-language-pack) - A comprehensive collection of tree-sitter parsers for 300+ languages, distributed as prebuilt wheels. + - [phonenumbers](https://github.com/daviddrysdale/python-phonenumbers) - Parsing, formatting, storing and validating international phone numbers. + - [parsy](https://github.com/python-parsy/parsy) - Easy, generic parser combinator library for creating parsers. +- Transliteration and Slugs + - [python-slugify](https://github.com/un33k/python-slugify) - A Python slugify library that translates unicode to ASCII. + - [unidecode](https://github.com/avian2/unidecode) - ASCII transliterations of Unicode text. +- Unique identifiers + - [shortuuid](https://github.com/skorokithakis/shortuuid) - A generator library for concise, unambiguous and URL-safe UUIDs. + - [sqids](https://github.com/sqids/sqids-python) - A library for generating short unique IDs from numbers. ### HTML Manipulation From 043cb6d377e2b03090b8bf6d7852645a2e908d63 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:09:18 +0800 Subject: [PATCH 131/168] feat: add charset-normalizer to Text Processing > Encoding and Unicode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ecosystem's default encoding detector — requests switched to it in 2021 and 2026 guidance names it the choice for new projects (web-verified). 1.73B downloads/month (pepy; heavily requests-transitive, but default-status is the point), pushed 2026-08. Co-obvious with chardet, which retains a verified accuracy claim — the PyQt/PySide pair shape. Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dc936e314e..daae4b0095 100644 --- a/README.md +++ b/README.md @@ -854,6 +854,7 @@ _Libraries for working with graphical user interface applications._ _Libraries for parsing and manipulating plain texts._ - Encoding and Unicode + - [charset-normalizer](https://github.com/jawah/charset_normalizer) - Universal character encoding detector, the default of the requests ecosystem. - [chardet](https://github.com/chardet/chardet) - Python character encoding detector. - [ftfy](https://github.com/rspeer/python-ftfy) - Makes Unicode text less broken and more consistent automagically. - General From db9c26234239c6f8d33be85371c4d0ee762224a3 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:09:32 +0800 Subject: [PATCH 132/168] feat: add rapidfuzz, minting Text Processing > Fuzzy Matching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The industry's fuzzy string matching answer (web-verified: the production recommendation over thefuzz — same API, MIT license, C++ speed — and preferred over textdistance for string metrics). 181.7M downloads/month (pepy), 4.1K stars, pushed 2026-08. Sole obvious choice; the subcategory label rides this commit so it is never empty, completing the displacement of textdistance. Co-Authored-By: Claude --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index daae4b0095..4e54b7eb92 100644 --- a/README.md +++ b/README.md @@ -857,6 +857,8 @@ _Libraries for parsing and manipulating plain texts._ - [charset-normalizer](https://github.com/jawah/charset_normalizer) - Universal character encoding detector, the default of the requests ecosystem. - [chardet](https://github.com/chardet/chardet) - Python character encoding detector. - [ftfy](https://github.com/rspeer/python-ftfy) - Makes Unicode text less broken and more consistent automagically. +- Fuzzy Matching + - [rapidfuzz](https://github.com/rapidfuzz/RapidFuzz) - Rapid fuzzy string matching using various string metrics, with a C++ core. - General - [difflib](https://docs.python.org/3/library/difflib.html) - (Python standard library) Helpers for computing deltas. - [pyfiglet](https://github.com/pwaller/pyfiglet) - An implementation of figlet written in Python. From ad698c28765d7c9125a286baffe3b27d9d4bc010 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:09:52 +0800 Subject: [PATCH 133/168] audit: sweep HTML Manipulation, drop html-to-markdown, pyquery, tinycss2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tiers: beautifulsoup4 (renamed from beautifulsoup — the bare PyPI name is the abandoned bs3 shim; 451.4M/mo, docs link per the PyQt precedent), lxml (401.3M/mo), xmltodict (124.5M/mo) obvious choices; markupsafe (820.5M/mo — the section's biggest raw count, but jinja-transitive infrastructure, so challenger on judgment; watch: quiet since 2025-09) and justhtml (67.8K/mo, 1.1K stars in two years — trajectory judgment on a young pure-Python HTML5 parser) challengers. Removed: - html-to-markdown — coordinated multi-entry self-promotion (automatic-rejection rule): PyPI provenance verified to xberg-io, the org's fourth planted entry overall. 1.5M downloads/month is real but the rule stands. - pyquery — 2.2M downloads/month and an active repo (pushed 2026-07); editorial drop at cap: the jQuery-style API is the least-reached-for of the keeps. Judgment call. - tinycss2 — 110.5M downloads/month is transitive (weasyprint declares it a hard dependency, verified in PyPI metadata) against 190 stars; a CSS parser mis-homed in an HTML/XML section with no better home. Judgment call. Co-Authored-By: Claude --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4e54b7eb92..4c8203d09f 100644 --- a/README.md +++ b/README.md @@ -881,14 +881,11 @@ _Libraries for parsing and manipulating plain texts._ _Libraries for working with HTML and XML._ -- [beautifulsoup](https://www.crummy.com/software/BeautifulSoup/bs4/doc/) - Providing Pythonic idioms for iterating, searching, and modifying HTML or XML. -- [html-to-markdown](https://github.com/xberg-io/html-to-markdown) - A fast, CommonMark-compliant HTML to Markdown converter with a Rust core, tolerant of malformed HTML. -- [justhtml](https://github.com/EmilStenstrom/justhtml/) - A pure Python HTML5 parser that just works. +- [beautifulsoup4](https://www.crummy.com/software/BeautifulSoup/bs4/doc/) - Providing Pythonic idioms for iterating, searching, and modifying HTML or XML. - [lxml](https://github.com/lxml/lxml) - A very fast, easy-to-use and versatile library for handling HTML and XML. -- [markupsafe](https://github.com/pallets/markupsafe) - Implements a XML/HTML/XHTML Markup safe string for Python. -- [pyquery](https://github.com/gawel/pyquery) - A jQuery-like library for parsing HTML. -- [tinycss2](https://github.com/Kozea/tinycss2) - A low-level CSS parser and generator written in Python. - [xmltodict](https://github.com/martinblech/xmltodict) - Working with XML feel like you are working with JSON. +- [markupsafe](https://github.com/pallets/markupsafe) - Implements a XML/HTML/XHTML Markup safe string for Python. +- [justhtml](https://github.com/EmilStenstrom/justhtml/) - A pure Python HTML5 parser that just works. ### File Format Processing From 15cd51c04ceeae73e0782705334bcf20c1f7764c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:10:10 +0800 Subject: [PATCH 134/168] style: re-tier File Manipulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No removals. mimetypes and pathlib (standard library) lead alphabetically under the stdlib-first rule; watchfiles (389.3M/mo, partly uvicorn-transitive — the riser) completes the obvious choices; watchdog (113.3M/mo, the demoted incumbent, Second Tier) and python-magic (32.3M/mo) challengers. Co-Authored-By: Claude --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4c8203d09f..033730f81b 100644 --- a/README.md +++ b/README.md @@ -924,9 +924,9 @@ _Libraries for file manipulation._ - [mimetypes](https://docs.python.org/3/library/mimetypes.html) - (Python standard library) Map filenames to MIME types. - [pathlib](https://docs.python.org/3/library/pathlib.html) - (Python standard library) A cross-platform, object-oriented path library. -- [python-magic](https://github.com/ahupp/python-magic) - A Python interface to the libmagic file type identification library. -- [watchdog](https://github.com/gorakhargosh/watchdog) - API and shell utilities to monitor file system events. - [watchfiles](https://github.com/samuelcolvin/watchfiles) - Simple, modern and fast file watching and code reload in python. +- [watchdog](https://github.com/gorakhargosh/watchdog) - API and shell utilities to monitor file system events. +- [python-magic](https://github.com/ahupp/python-magic) - A Python interface to the libmagic file type identification library. **Media** From 5249b756ce5b8424ece4202ba8573169b678dff5 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:21:08 +0800 Subject: [PATCH 135/168] refactor: re-home fasthtml to Web Frameworks > Asynchronous MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer-adjudicated close of the standing flag: fasthtml runs on Starlette and Uvicorn (ASGI), so Synchronous was the wrong shelf. It lands as a third challenger behind starlette and tornado's obvious choices — the use case holds 5 with 3 challengers by explicit maintainer override (Async I/O precedent; the awesome-fasthtml sub-item rides along). 1.19M downloads/month as python-fasthtml. Co-Authored-By: Claude --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 033730f81b..6b31695b0b 100644 --- a/README.md +++ b/README.md @@ -251,13 +251,13 @@ _Traditional full stack web frameworks. Also see [Web APIs](#web-apis)._ - [bottle](https://github.com/bottlepy/bottle) - A fast and simple micro-framework distributed as a single file with no dependencies. - [pyramid](https://github.com/Pylons/pyramid) - A small, fast, down-to-earth, open source Python web framework. - [awesome-pyramid](https://github.com/uralbash/awesome-pyramid) - - [fasthtml](https://github.com/AnswerDotAI/fasthtml) - The fastest way to create an HTML app. - - [awesome-fasthtml](https://github.com/amosgyamfi/awesome-fasthtml) - Asynchronous - [starlette](https://github.com/Kludex/starlette) - A lightweight ASGI framework and toolkit for building high-performance async services. - [tornado](https://github.com/tornadoweb/tornado) - A web framework and asynchronous networking library. - [litestar](https://github.com/litestar-org/litestar) - Production-ready, capable and extensible ASGI Web framework. - [reflex](https://github.com/reflex-dev/reflex) - A framework for building reactive, full-stack web applications entirely with Python. + - [fasthtml](https://github.com/AnswerDotAI/fasthtml) - The fastest way to create an HTML app. + - [awesome-fasthtml](https://github.com/amosgyamfi/awesome-fasthtml) ### Web APIs From e5f7b5bc2eb35fad07f5f2ffffa4620c01cffb14 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:21:21 +0800 Subject: [PATCH 136/168] style: update graphify link to the moved Graphify-Labs repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The safishamsi/graphify URL is a stale redirect — the repo moved to Graphify-Labs/graphify (verified via the GitHub API). Maintainer declined the Agent Skills re-home; the entry stays in Data Visualization > Specialized with its link fixed. Co-Authored-By: Claude --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b31695b0b..4ee5c99e2a 100644 --- a/README.md +++ b/README.md @@ -517,7 +517,7 @@ _Libraries for visualizing data. Also see [awesome-javascript](https://github.co - Specialized - [cartopy](https://github.com/SciTools/cartopy) - A cartographic python library with matplotlib support. - [pygraphviz](https://github.com/pygraphviz/pygraphviz/) - Python interface to [Graphviz](https://www.graphviz.org/). - - [graphify](https://github.com/safishamsi/graphify) - Turn any folder of code, SQL schemas, docs, papers, images, or videos into a queryable knowledge graph. + - [graphify](https://github.com/Graphify-Labs/graphify) - Turn any folder of code, SQL schemas, docs, papers, images, or videos into a queryable knowledge graph. - Dashboards and Apps - [streamlit](https://github.com/streamlit/streamlit) - A framework which lets you build dashboards, generate reports, or create chat apps in minutes. - [gradio](https://github.com/gradio-app/gradio) - Build and share machine learning apps, all in Python. From 441f206d71814a99848c6b260df288890c9057c3 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:24:38 +0800 Subject: [PATCH 137/168] feat: add pathway to Data Ingestion / ETL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-admission on maintainer word, reversing the Data Analysis sweep's drop (f3c920d — the xlsxwriter reversal precedent): the drop was partly a mis-homing casualty, since its honest home, an ETL use case, did not exist then. The repo self-describes as a Python ETL framework for stream processing and LLM/RAG pipelines: 62.5K stars, pushed daily; 16.5K downloads/month is weak for the star count and noted. Enters as challenger behind dlt (7.8M/mo). Co-Authored-By: Claude --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4ee5c99e2a..95b44b4617 100644 --- a/README.md +++ b/README.md @@ -490,6 +490,7 @@ _Libraries for data extraction, transformation, and loading pipelines across mul - General - [dlt](https://github.com/dlt-hub/dlt) - A Python library for building data pipelines with automatic schema inference, incremental loading, and support for multiple sources and destinations. + - [pathway](https://github.com/pathwaycom/pathway) - Python ETL framework for stream processing, real-time analytics, LLM pipelines, and RAG. - Financial Data - [yfinance](https://github.com/ranaroussi/yfinance) - Easy Pythonic way to download market and financial data from Yahoo Finance. - [akshare](https://github.com/akfamily/akshare) - A financial data interface library, built for human beings! From f60d5b4a08c25b437548cd3746393609b06b2e73 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:25:15 +0800 Subject: [PATCH 138/168] style: move fasthtml back to Web Frameworks > Synchronous MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer reversal of c0a31ce, restoring the entry and its awesome-fasthtml sub-item to their prior position. The challenger-limit override that rode the move is withdrawn with it — Asynchronous returns to 4 entries within the standard cap shape. Co-Authored-By: Claude --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 95b44b4617..5540980d82 100644 --- a/README.md +++ b/README.md @@ -251,13 +251,13 @@ _Traditional full stack web frameworks. Also see [Web APIs](#web-apis)._ - [bottle](https://github.com/bottlepy/bottle) - A fast and simple micro-framework distributed as a single file with no dependencies. - [pyramid](https://github.com/Pylons/pyramid) - A small, fast, down-to-earth, open source Python web framework. - [awesome-pyramid](https://github.com/uralbash/awesome-pyramid) + - [fasthtml](https://github.com/AnswerDotAI/fasthtml) - The fastest way to create an HTML app. + - [awesome-fasthtml](https://github.com/amosgyamfi/awesome-fasthtml) - Asynchronous - [starlette](https://github.com/Kludex/starlette) - A lightweight ASGI framework and toolkit for building high-performance async services. - [tornado](https://github.com/tornadoweb/tornado) - A web framework and asynchronous networking library. - [litestar](https://github.com/litestar-org/litestar) - Production-ready, capable and extensible ASGI Web framework. - [reflex](https://github.com/reflex-dev/reflex) - A framework for building reactive, full-stack web applications entirely with Python. - - [fasthtml](https://github.com/AnswerDotAI/fasthtml) - The fastest way to create an HTML app. - - [awesome-fasthtml](https://github.com/amosgyamfi/awesome-fasthtml) ### Web APIs From 194b386d06f2ef2d0fc694f8af95b20bf0f3213a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:25:15 +0800 Subject: [PATCH 139/168] docs: codify the Override rule in CONTRIBUTING and CONTEXT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves decision 10's reservation on maintainer word: the 3+2/5 cap numbers stay as written — across the full prune they held everywhere except a handful of explicit overrides — and the override practice itself becomes a written rule: the maintainer may exceed any limit for a specific entry or use case by explicit decision, case-by-case, carrying no weight for submissions. CONTEXT.md gains the matching Override vocabulary entry. Co-Authored-By: Claude --- CONTEXT.md | 3 +++ CONTRIBUTING.md | 2 ++ 2 files changed, 5 insertions(+) diff --git a/CONTEXT.md b/CONTEXT.md index d7fb6b5342..986b6f4d2f 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -50,6 +50,9 @@ _Avoid_: Rising Star (old lane name), Hidden Gem (old lane name — concept remo **Second Tier**: A Challenger slot holding a demoted incumbent instead of a rising successor — a former Obvious Choice or fading community standard an Audit kept below the current Obvious Choices (clickhouse-driver behind the official client, dogpile.cache and django-cacheops behind cachetools and diskcache, django-haystack in Search). It counts against the two Challenger slots and is marked by position like any Challenger; the adoption-trajectory bar gates only new admissions, not demotions. +**Override**: +A maintainer decision, made in an Audit and explicitly recorded, that keeps an entry or use-case shape past a written limit — the activity line, the stability bar, a cap, or a structure rule. Case-by-case: an Override never loosens the written rule for any other entry, and submitters cannot cite one. + **Split**: Maintainer-only restructuring of an oversized Use Case into finer Use Cases (new Subcategories), considered before any trimming when the size reflects genuinely distinct jobs. A submitter's entry PR can never perform a Split. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 281df0cd15..089f21b495 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,6 +23,8 @@ Each use case lists at most: Hard maximum: 5 entries per use case. This is a qualitative bar first and a numeric backstop second — most use cases should carry fewer. +**Overrides**: the maintainer may exceed any limit on this page — the caps, the activity requirement, the stability requirement — for a specific entry or use case by explicit decision. An override is case-by-case; it does not loosen these rules for submissions, and citing one in a PR carries no weight. + **Displacement**: once a use case is at its cap, the only way in is to name the entry your project replaces and argue that yours does that entry's job better. One in, one out. **Standard library**: a standard-library module is listed only where the stdlib is itself the obvious choice for the use case (tomllib yes, unittest no). From 39eeab7dff302e8eedf7ba7b1f6a429d707bce16 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:57:15 +0800 Subject: [PATCH 140/168] docs: warn about wrong-package PyPI download counts The pypi downloads sweep looks up counts by README display name; when the display name differs from the canonical package, the row silently measures an unrelated squatter or a dead predecessor. Document the failure mode in both the fetcher's docstring and the audit skill so famous entries with off-looking counts get identity-verified before being cited. Co-Authored-By: Claude --- .claude/skills/audit-the-list/SKILL.md | 2 +- website/fetch_pypi_downloads_via_clickpy.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.claude/skills/audit-the-list/SKILL.md b/.claude/skills/audit-the-list/SKILL.md index 961b3c7f73..4c2b576cd0 100644 --- a/.claude/skills/audit-the-list/SKILL.md +++ b/.claude/skills/audit-the-list/SKILL.md @@ -18,7 +18,7 @@ Fetch live evidence for every entry in scope before judging anything (CLAUDE.md - **Downloads/month**: `cd website && UV_PYTHON=3.13 uv run python fetch_pypi_downloads_via_clickpy.py` — free keyless ClickPy sweep of the full README, sole writer of `data/pypi_downloads.tsv` (rewritten from scratch each run; header row, every row stamped with its `fetched_at` date). A cache whose `fetched_at` is within the last 7 days is current enough for verdicts — skip the sweep; older than that, re-run it (costs ~1s). Cross-checks print to stdout, take explicit names, and never touch the cache: `fetch_pypi_downloads_via_bigquery.py ...` (canonical source, maintainer's own GCP account, `--dry-run` first — the docstring carries the cost constraints; full-README sweeps exceed the free tier, keep name lists small), `fetch_pypi_downloads_via_pepy.py ...` (needs `PEPY_TECH_API_KEY` in repo-root `.env`, throttled to 5 requests/minute), or `https://pypistats.org/api/packages/{name}/recent` paced 8s or slower. pypistats excludes mirror/CI traffic; ClickPy, BigQuery, and pepy include it — never mix sources within one comparison. - **Repo state**: archived flag, last push, created date, stars, description — `gh api repos/{owner}/{repo}`, GitLab API for GitLab-hosted projects. -- **PyPI metadata** (`https://pypi.org/pypi/{name}/json`) wherever a name might not be the canonical package — ownership collisions and wrong display names surface here. +- **PyPI metadata** (`https://pypi.org/pypi/{name}/json`) wherever a name might not be the canonical package — ownership collisions and wrong display names surface here. Wrong-package cache rows are common: the sweep looks up README display names, so when the display name differs from the canonical package, the row silently measures an unrelated squatter or a dead predecessor. When a famous entry shows a count that looks off (too small, or absurdly round), verify identity before citing it, and fetch the canonical package's count via pepy. Done when every entry in scope has downloads (or a stated no-signal reason), repo state, and a confirmed PyPI name. diff --git a/website/fetch_pypi_downloads_via_clickpy.py b/website/fetch_pypi_downloads_via_clickpy.py index e384b365ed..1e7c1a262b 100644 --- a/website/fetch_pypi_downloads_via_clickpy.py +++ b/website/fetch_pypi_downloads_via_clickpy.py @@ -12,7 +12,11 @@ This script is the sole writer of data/pypi_downloads.tsv and rewrites it from scratch each run, so entries removed from README.md drop out -naturally; names with no PyPI rows are written as NOT_FOUND. The file +naturally; names with no PyPI rows are written as NOT_FOUND. Counts are +looked up by README display name: when the display name differs from the +canonical PyPI package, the row silently measures the wrong package (a +squatter or a dead predecessor) — verify identity at +pypi.org/pypi/{name}/json before citing a count. The file starts with a header row (name, downloads, fetched_at) and every row carries the sweep date: a cache fetched within the last 7 days is current enough for audit verdicts, so only re-run when older. Cross-checks From c034c88e91bcf4e7ca9212979ff1248141da580e Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:57:21 +0800 Subject: [PATCH 141/168] docs: add audit log registry for maintainer overrides Git history already archives every removal's reason via commit body, but it can't be scanned at a glance. docs/audit-logs.md is the at-a-glance register of overrides (naming exceptions, mature-stable keeps) allowed by CONTRIBUTING.md. Drop the docs/* gitignore exclusion (and stale .superpowers/ and skills-lock.json entries) so the file and future doc additions outside docs/adr/ can be tracked. Co-Authored-By: Claude --- .gitignore | 8 +------- docs/audit-logs.md | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 docs/audit-logs.md diff --git a/.gitignore b/.gitignore index b4d552e4f0..1f2c6f1e01 100644 --- a/.gitignore +++ b/.gitignore @@ -13,12 +13,6 @@ __pycache__/ website/output/ website/data/ -# docs (except decision records) -docs/* -!docs/adr/ - # agents -tmp/ -.superpowers/ .playwright-cli/ -skills-lock.json +tmp/ diff --git a/docs/audit-logs.md b/docs/audit-logs.md new file mode 100644 index 0000000000..93fad35ebe --- /dev/null +++ b/docs/audit-logs.md @@ -0,0 +1,33 @@ +# Audit Log + +awesome-python is audited section by section. Every entry gets re-verified against live data, and every removal lands in a commit whose body carries the reason. Git history is the archive. This file is the at-a-glance register of maintainer decisions that a single commit can't show. + +## Overrides + +[CONTRIBUTING.md](../CONTRIBUTING.md) allows the maintainer to exceed any limit for a specific entry or use case. Each override is recorded here. + +### Naming Exceptions + +Display names follow the canonical PyPI package name. These entries keep a different name by maintainer decision: + +- autobahn-python -- `autobahn`. +- django-rest-framework -- `djangorestframework`. +- django-rules -- `rules`. +- fasthtml -- `python-fasthtml`. +- jinja -- `Jinja2`. +- mem0 -- `mem0ai`. +- pangu.py -- `pangu`. +- playwright-python -- `playwright`. +- pytorch -- `torch`. +- strawberry -- `strawberry-graphql`. +- strawberry-django -- `strawberry-graphql-django`. + +### Mature-stable Keeps + +These entries sit past the 12-month activity requirement without an override. Each one is kept by editorial judgment: mature, stable, and no successor exists. + +- sortedcontainers +- jinja +- itsdangerous +- jieba +- ftfy From 3e43fa13badd00583d7b4e22e11196bb79feadc9 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:57:25 +0800 Subject: [PATCH 142/168] docs: clarify cross-section re-homes and resources scope in audit rules Cross-section re-homes now ride the originating audit's commit instead of needing a separate one, since both sides of the move land in one diff. Also note that Resources sections are out of audit scope and never parsed by the website, so they're not project entries subject to the one-entry-per-commit rule. Co-Authored-By: Claude --- CLAUDE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 47ac9487b6..1cf71b7332 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,7 +9,8 @@ An opinionated guide to the best Python frameworks, libraries, tools, and resour [CONTRIBUTING.md](CONTRIBUTING.md) holds the admission rules, quality requirements, rejection rules, entry format, and ordering. Apply it whenever adding or removing an entry — direct commits included, not only PR reviews. - Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Judging tiers — obvious choice vs challenger — also requires WebSearch evidence (adoption trajectory, community sentiment), not download counts alone. Training-data recollections are not evidence; label anything unverifiable as a judgment call. -- One entry per commit when adding or deleting entries. Exceptions: a prune sweep is one commit per section, its body listing each removal with its reason; format, wording, or categorization changes may be bundled. +- One entry per commit when adding or deleting entries. Exceptions: a prune sweep is one commit per section, its body listing each removal with its reason; format, wording, or categorization changes may be bundled. Cross-section re-homes ride the originating audit's commit (both sides of the move in one diff). +- Resources sections are not project entries: out of audit scope, and the website never parses them. - Sponsor placement never influences which projects get listed — see [SPONSORSHIP.md](SPONSORSHIP.md). ## Gotchas From deae0e0b728ab7fa405f60411e4d0f7827647b28 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:57:29 +0800 Subject: [PATCH 143/168] docs: broaden Obvious Choice signal and note Cap has no floor Extend the known failure-mode list for PyPI download counts beyond model weights to any project consumed outside pip (SDK downloads like renpy, deployed services like thumbor). Also clarify that the per-Use- Case Cap is a ceiling, not a floor: a freshly minted Use Case may hold a single entry. Co-Authored-By: Claude --- CONTEXT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index 986b6f4d2f..cda364e5ff 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -33,11 +33,11 @@ The scope test for what belongs on the list at all: Python developers use it in _Avoid_: Python-first, written-in-Python (old requirement — removed) **Obvious Choice**: -An entry an experienced Python developer would name unprompted when asked "what do I use for [Use Case]?". Certified by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars; judgment overrides the signal's known failure modes (CI-inflated counts, model releases consumed as weights rather than pip installs, large-but-specific audiences misread as "niche"). A standard-library module holds a slot only when it is itself the Obvious Choice for the Use Case, not merely relevant to it. +An entry an experienced Python developer would name unprompted when asked "what do I use for [Use Case]?". Certified by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars; judgment overrides the signal's known failure modes (CI-inflated counts, model releases consumed as weights rather than pip installs — extended to any project consumed outside pip: SDK downloads like renpy, deployed services like thumbor — and large-but-specific audiences misread as "niche"). A standard-library module holds a slot only when it is itself the Obvious Choice for the Use Case, not merely relevant to it. _Avoid_: Industry Standard (old lane name), awesome (unfalsifiable) **Cap**: -The per-Use-Case entry limit: up to 3 Obvious Choices plus up to 2 Challengers, hard maximum 5. A qualitative bar first, a numeric backstop second. +The per-Use-Case entry limit: up to 3 Obvious Choices plus up to 2 Challengers, hard maximum 5. A qualitative bar first, a numeric backstop second — and a ceiling, not a floor: a minted Use Case may hold a single entry. **Displacement**: The only admission path into a full Use Case: the PR names the entry it replaces and argues the newcomer does that entry's job better. One in, one out. From 2c50d9e63a0abe76ad07cc12549791b43051949e Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:57:31 +0800 Subject: [PATCH 144/168] docs: document gitignored output and orphan-key behavior Note that data/github_stars.json is gitignored and fetched by CI at deploy time, so local runs are preview-only and should never be committed; entries removed from README.md just leave harmless orphan keys behind. Co-Authored-By: Claude --- website/fetch_github_stars.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/website/fetch_github_stars.py b/website/fetch_github_stars.py index 48aaacf79c..3f4518854e 100644 --- a/website/fetch_github_stars.py +++ b/website/fetch_github_stars.py @@ -1,5 +1,10 @@ #!/usr/bin/env python3 -"""Fetch GitHub star counts and owner info for all GitHub repos in README.md.""" +"""Fetch GitHub star counts and owner info for all GitHub repos in README.md. + +The output file (data/github_stars.json) is gitignored; CI fetches it at +deploy time, so local runs are for previews only — never commit the data. +Entries removed from README.md leave harmless orphan keys behind. +""" import json import os From 2c2ce2fcaca7a3e46e4798cae811bdb11afc4f93 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 15:57:36 +0800 Subject: [PATCH 145/168] docs: document empirically verified README parsing behavior Capture parser quirks worth knowing before editing README.md: everything above is ignored, new subcategories need no parser change, a standalone all-bold paragraph becomes a Thematic Group marker, prose after leaks into llms.txt, and the build's "Total entries" figure counts sub-items rather than just entries. Co-Authored-By: Claude --- website/readme_parser.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/website/readme_parser.py b/website/readme_parser.py index 61bf1e982e..84887d0f77 100644 --- a/website/readme_parser.py +++ b/website/readme_parser.py @@ -1,4 +1,13 @@ -"""Parse README.md into structured section data using markdown-it-py AST.""" +"""Parse README.md into structured section data using markdown-it-py AST. + +Empirically verified behavior worth knowing before editing README.md: +everything above `## Projects` is ignored; new subcategories need no +parser change (a bullet without a leading link plus indented entries); +a standalone all-bold paragraph inside the Projects region becomes a +Thematic Group marker; prose placed right after `## Categories` leaks +into llms.txt; the build's "Total entries" figure counts sub-items +(indented links under an entry), not just entries. +""" from __future__ import annotations From cfb60a633f449e53dd2b91235c5721101403d08a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:06:34 +0800 Subject: [PATCH 146/168] docs: codify dual-listing policy in CONTRIBUTING.md The maintainer decided how duplicate entries across categories should be handled (e.g. uv listed in both Environment Management and Package Management): each slot must earn its place independently, entries are listed in full with identical lines rather than a cross-reference, description edits update every copy in the same commit, and each slot is audited on its own. Co-Authored-By: Claude --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 089f21b495..1678cbd5f8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,6 +27,8 @@ Hard maximum: 5 entries per use case. This is a qualitative bar first and a nume **Displacement**: once a use case is at its cap, the only way in is to name the entry your project replaces and argue that yours does that entry's job better. One in, one out. +**Dual-listing**: a tool may hold entries in multiple use cases, but only when it earns its slot in each independently — uv sits in both Environment Management and Package Management. List the full entry in each home with identical lines; never a "see X above" note, since the website only renders list items. Description edits update every copy in the same commit. Each slot is audited on its own: dropping one home keeps the other, and dropping the tool entirely removes all copies in one commit. Dual-listing is a maintainer decision; a PR adding a second home for an existing entry is treated as a duplicate. + **Standard library**: a standard-library module is listed only where the stdlib is itself the obvious choice for the use case (tomllib yes, unittest no). **Evidence**: admission is decided by maintainer editorial judgment, informed primarily by PyPI download counts rather than GitHub stars. Judgment overrides the signal's known failure modes (CI-inflated counts, model releases consumed as weights rather than pip installs, large-but-specific audiences misread as "niche"). The maintainer's decision is final. From cccfa183a9a224e230b8cd1352ed56b033a0b6f3 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:11:00 +0800 Subject: [PATCH 147/168] docs: rewrite PR template to match shortlist rules The old template used a stars-based tier system (Industry Standard / Rising Star / Hidden Gem) that contradicted the current CONTRIBUTING.md, which judges entries by obvious-choice/challenger tiers, favors PyPI downloads over stars, and requires Displacement when a use case is at its cap. The new template reflects those rules and adds a checklist item pointing contributors to CONTRIBUTING.md. Co-Authored-By: Claude --- .github/PULL_REQUEST_TEMPLATE.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 05c3b80477..865e26ad16 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,24 +1,26 @@ ## Project -[Project Name](url) +[project-name](url) ## Checklist +- [ ] I read [CONTRIBUTING.md](https://github.com/vinta/awesome-python/blob/master/CONTRIBUTING.md) - awesome-python is a shortlist, not a catalog - [ ] One project per PR - [ ] PR title format: `Add project-name` -- [ ] Entry format: `- [project-name](url) - Description ending with period.` -- [ ] Description is concise and short +- [ ] Entry format: `- [pypi-name](https://github.com/owner/repo) - Description ending with period.` +- [ ] Display name is the PyPI package name +- [ ] Placed in an existing use case (new sections and subcategories are maintainer-only) +- [ ] Meets all Quality Requirements: active, stable, documented, at least 1 month old -## Why This Project Is Awesome +## Which Tier -Which criterion does it meet? (pick one) +Pick one: -- [ ] **Industry Standard** - The go-to tool for a specific use case -- [ ] **Rising Star** - 5000+ stars in < 2 years, significant adoption -- [ ] **Hidden Gem** - Exceptional quality, solves niche problems elegantly +- [ ] **Obvious choice** - a tool an experienced Python developer would name unprompted for this use case +- [ ] **Challenger** - not yet the obvious choice, but a credible successor to one. Give adoption-trajectory evidence, not popularity alone. Explain: -## How It Differs +## Displacement -If similar entries exist, what makes this one unique? +If the use case is at its cap, name the entry your project replaces and argue that yours does that entry's job better. One in, one out. From 68b15a4644eefab12c849c3cf5b9c05e976b482e Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:13:43 +0800 Subject: [PATCH 148/168] docs: rephrase obvious-choice criterion in PR template Reuses CONTRIBUTING.md's plainer 'would name when asked' phrasing instead of 'unprompted', per maintainer feedback that 'unprompted' didn't sound right. Co-Authored-By: Claude --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 865e26ad16..41890f4696 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -16,7 +16,7 @@ Pick one: -- [ ] **Obvious choice** - a tool an experienced Python developer would name unprompted for this use case +- [ ] **Obvious choice** - a tool an experienced Python developer would name when asked "what do I use for this?" - [ ] **Challenger** - not yet the obvious choice, but a credible successor to one. Give adoption-trajectory evidence, not popularity alone. Explain: From 08fdfa6a88ac1d403d36dd3b2c23b7ed74723012 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:14:36 +0800 Subject: [PATCH 149/168] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5540980d82..71867232e3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # [Awesome Python](https://awesome-python.com/) -An opinionated guide to the best Python frameworks, libraries, tools, and resources. +The definitive list that answers "I want to do X in Python, which tool should I use?" - An opinionated guide to the best Python frameworks, libraries, tools, and projects. **Visit the [website](https://awesome-python.com/) to search and filter projects more easily.** From 0e9ae0cb04c04a4390dba589c89500eac132504e Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:25:10 +0800 Subject: [PATCH 150/168] clean up --- CONTRIBUTING.md | 4 ++-- docs/audit-logs.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1678cbd5f8..e90db05a23 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,7 @@ A **use case** is one distinct job a reader needs done. Use cases are defined by Each use case lists at most: -- **Up to 3 obvious choices** — tools an experienced Python developer would name unprompted when asked "what do I use for this?" +- **Up to 3 obvious choices** — tools an experienced Python developer would name when asked "what do I use for this?" - **Up to 2 challengers** — tools that are not yet the obvious choice but are credible successors to one. Admission as a challenger requires adoption-trajectory evidence, not popularity alone. Hard maximum: 5 entries per use case. This is a qualitative bar first and a numeric backstop second — most use cases should carry fewer. @@ -27,7 +27,7 @@ Hard maximum: 5 entries per use case. This is a qualitative bar first and a nume **Displacement**: once a use case is at its cap, the only way in is to name the entry your project replaces and argue that yours does that entry's job better. One in, one out. -**Dual-listing**: a tool may hold entries in multiple use cases, but only when it earns its slot in each independently — uv sits in both Environment Management and Package Management. List the full entry in each home with identical lines; never a "see X above" note, since the website only renders list items. Description edits update every copy in the same commit. Each slot is audited on its own: dropping one home keeps the other, and dropping the tool entirely removes all copies in one commit. Dual-listing is a maintainer decision; a PR adding a second home for an existing entry is treated as a duplicate. +**Dual-listing**: a tool may hold entries in multiple use cases, but only when it earns its slot in each independently. List the full entry in each home with identical lines; never a "see X above" note, since the website only renders list items. Description edits update every copy in the same commit. Each slot is audited on its own: dropping one home keeps the other, and dropping the tool entirely removes all copies in one commit. Dual-listing is a maintainer decision; a PR adding a second home for an existing entry is treated as a duplicate. **Standard library**: a standard-library module is listed only where the stdlib is itself the obvious choice for the use case (tomllib yes, unittest no). diff --git a/docs/audit-logs.md b/docs/audit-logs.md index 93fad35ebe..80407a2ff7 100644 --- a/docs/audit-logs.md +++ b/docs/audit-logs.md @@ -26,8 +26,8 @@ Display names follow the canonical PyPI package name. These entries keep a diffe These entries sit past the 12-month activity requirement without an override. Each one is kept by editorial judgment: mature, stable, and no successor exists. -- sortedcontainers -- jinja +- ftfy - itsdangerous - jieba -- ftfy +- jinja +- sortedcontainers From f13075b2aff0414c088520db1b6e274f3f623642 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:44:38 +0800 Subject: [PATCH 151/168] refactor: re-home aws-sdk-pandas from pandas sub-item to ETL General Sub-item policy reserves sub-items for awesome-* links. aws-sdk-pandas promoted out as awswrangler in Data Ingestion / ETL > General (85.3M downloads/mo, 10x dlt, active). Co-Authored-By: Claude --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 71867232e3..5043d37f2f 100644 --- a/README.md +++ b/README.md @@ -480,7 +480,6 @@ _Libraries for serializing complex data types._ _Libraries for data analysis._ - [pandas](https://github.com/pandas-dev/pandas) - A library providing high-performance, easy-to-use data structures and data analysis tools. - - [aws-sdk-pandas](https://github.com/aws/aws-sdk-pandas) - [polars](https://github.com/pola-rs/polars) - A fast DataFrame library implemented in Rust with a Python API. - [ibis-framework](https://github.com/ibis-project/ibis) - A portable Python dataframe library with a single API for 20+ backends. @@ -489,6 +488,7 @@ _Libraries for data analysis._ _Libraries for data extraction, transformation, and loading pipelines across multiple sources and destinations._ - General + - [awswrangler](https://github.com/aws/aws-sdk-pandas) - Pandas integration with AWS services like Athena, Glue, Redshift, S3, and DynamoDB. - [dlt](https://github.com/dlt-hub/dlt) - A Python library for building data pipelines with automatic schema inference, incremental loading, and support for multiple sources and destinations. - [pathway](https://github.com/pathwaycom/pathway) - Python ETL framework for stream processing, real-time analytics, LLM pipelines, and RAG. - Financial Data From 63a1eadd30755834dc4ede328831f4469f72e6c1 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:45:26 +0800 Subject: [PATCH 152/168] docs: remove typeshed sub-item from under mypy Not a tool readers install: type checkers bundle it automatically as a stub collection, it has no PyPI package, and no standalone use case. The Type Checkers subcategory label already links to awesome-python-typing for ecosystem depth. Co-Authored-By: Claude --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 5043d37f2f..949de42fe7 100644 --- a/README.md +++ b/README.md @@ -617,7 +617,6 @@ _Tools of static analysis, linters and code quality checkers. Also see [awesome- - [rope](https://github.com/python-rope/rope) - Rope is a python refactoring library. - Type Checkers - [awesome-python-typing](https://github.com/typeddjango/awesome-python-typing) - [mypy](https://github.com/python/mypy) - Check variable types during compile time. - - [typeshed](https://github.com/python/typeshed) - [ty](https://github.com/astral-sh/ty) - An extremely fast Python type checker and language server. - [pyright](https://github.com/microsoft/pyright) - Full-featured static type checker for Python from Microsoft, the engine behind Pylance. - [pyrefly](https://github.com/facebook/pyrefly) - A fast type checker and language server for Python. From b0434abae6efdaf907f11394a2b7660510bfd20a Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:45:57 +0800 Subject: [PATCH 153/168] refactor: promote mkdocs-material to full Documentation entry Was a sub-item under mkdocs. By downloads it ranks second in the section at 17.6M/mo (ClickPy), above mkdocs' 17.4M, and it powers FastAPI, Pydantic, and Ruff/Polars docs (27,269 stars, pushed 2026-08-09). Documentation now sits at its 5-entry cap. Co-Authored-By: Claude --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 949de42fe7..975fd97648 100644 --- a/README.md +++ b/README.md @@ -690,8 +690,8 @@ _Libraries for generating project documentation._ - [sphinx](https://github.com/sphinx-doc/sphinx/) - Python Documentation generator. - [awesome-sphinxdoc](https://github.com/ygzgxyz/awesome-sphinxdoc) +- [mkdocs-material](https://github.com/squidfunk/mkdocs-material) - A documentation framework and Material Design theme built on MkDocs. - [mkdocs](https://github.com/mkdocs/mkdocs/) - Markdown friendly documentation generator. - - [mkdocs-material](https://github.com/squidfunk/mkdocs-material) - [diagrams](https://github.com/mingrammer/diagrams) - Diagram as Code. - [pdoc](https://github.com/mitmproxy/pdoc) - Epydoc replacement to auto generate API documentation for Python libraries. From 49b229bab454e63396209105311b22f96d23af96 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:46:31 +0800 Subject: [PATCH 154/168] refactor: promote flower from celery sub-item to full DevOps Monitoring entry Flower isn't a task queue, so nesting it under celery misclassified it; Task Queues is also at its entry cap. Monitoring and Processes is its honest home, ranking fourth by downloads (12.35M/mo ClickPy, between supervisor 17.0M and sh 11.8M), and Celery's own docs name it the recommended monitor. Repo pushed 2026-08-16 with 7,232 stars. This fills Monitoring and Processes to its 5-entry cap. Co-Authored-By: Claude --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 975fd97648..8201f70464 100644 --- a/README.md +++ b/README.md @@ -718,6 +718,7 @@ _Software and libraries for DevOps._ - [psutil](https://github.com/giampaolo/psutil) - A cross-platform process and system utilities module. - [sentry-sdk](https://github.com/getsentry/sentry-python) - Sentry SDK for Python. - [supervisor](https://github.com/Supervisor/supervisor) - Supervisor process control system for UNIX. + - [flower](https://github.com/mher/flower) - A real-time monitor and web admin for Celery task queues. - [sh](https://github.com/amoffat/sh) - A full-fledged subprocess replacement for Python. - Other - [borgbackup](https://github.com/borgbackup/borg) - A deduplicating archiver with compression and encryption. @@ -738,7 +739,6 @@ _Frameworks and libraries for Distributed Computing._ _Libraries for working with task queues._ - [celery](https://github.com/celery/celery) - An asynchronous task queue/job queue based on distributed message passing. - - [flower](https://github.com/mher/flower) - [rq](https://github.com/rq/rq) - Simple job queues for Python. - [dramatiq](https://github.com/Bogdanp/dramatiq) - A fast and reliable background task processing library for Python 3. - [huey](https://github.com/coleifer/huey) - Little multi-threaded task queue. From ecd9dea9e41c189b6881c09455f1226bf98e1de3 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:47:02 +0800 Subject: [PATCH 155/168] refactor: move pyenv-win from pyenv sub-item to full entry Re-homed pyenv-win from a pyenv sub-item (Environment Management) to a full entry in Microsoft Windows, placed before winpython by downloads (25.8k/mo vs 172). Actively maintained, pushed 2026-08-14, 7,360 stars. Maintainer preference is to move sub-items to a fitting category rather than delete. Co-Authored-By: Claude --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8201f70464..a001b8f0e6 100644 --- a/README.md +++ b/README.md @@ -1041,7 +1041,6 @@ _Libraries for Python version and virtual environment management._ - [virtualenv](https://github.com/pypa/virtualenv) - A tool to create isolated Python environments. - [uv](https://github.com/astral-sh/uv) - An extremely fast Python version, package and project manager, written in Rust. - [pyenv](https://github.com/pyenv/pyenv) - Simple Python version management. - - [pyenv-win](https://github.com/pyenv-win/pyenv-win) ### Package Management @@ -1138,6 +1137,7 @@ _Python programming on Microsoft Windows._ - [pythonnet](https://github.com/pythonnet/pythonnet) - Python Integration with the .NET Common Language Runtime (CLR). - [pywin32](https://github.com/mhammond/pywin32) - Python Extensions for Windows. +- [pyenv-win](https://github.com/pyenv-win/pyenv-win) - A Python version manager for Windows ([pyenv](https://github.com/pyenv/pyenv) fork). - [winpython](https://github.com/winpython/winpython) - Portable development environment for Windows 10/11. ### Miscellaneous From c39e4d6bf5246034952536d988ebdbae4001cb7e Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:47:34 +0800 Subject: [PATCH 156/168] docs: restrict sub-items to awesome-* also-see links Removed the companion-project clause from the Sub-item definition in CONTEXT.md's vocabulary. Its examples (aws-sdk-pandas under pandas, flower under celery) went stale this sitting: those companions were promoted, re-homed, or deleted. Per the maintainer's 2026-08-16 policy decision, sub-items are now reserved for awesome-* also-see links only - a companion project must earn a full Entry in its proper Use Case or not be listed. Co-Authored-By: Claude --- CONTEXT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTEXT.md b/CONTEXT.md index cda364e5ff..434afbc77b 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -10,7 +10,7 @@ The editorial domain of awesome-python: which projects the list carries, how the A single listed project: `- [name](url) - Description.` The unit that is admitted, displaced, or pruned. Named by PyPI package name when one exists, else by repository name. **Sub-item**: -An indented link under an Entry (awesome-django under django, aws-sdk-pandas under pandas, flower under celery). Not an Entry: it holds no slot, does not count against the Cap, and rides its parent — re-homed or removed with it. Maintainer-only placement, for a companion project whose job is inseparable from its parent's (flower monitors celery) or an awesome-* also-see list. +An indented awesome-* also-see link under an Entry (awesome-django under django, awesome-pytest under pytest). Not an Entry: it holds no slot, does not count against the Cap, and rides its parent — re-homed or removed with it. Maintainer-only placement, and only for awesome-* lists: a companion project either earns a full Entry in its proper Use Case or is not listed. **Thematic Group**: A bold group line (e.g. "AI & ML", "Web Development") that clusters Sections in the TOC and the Projects body. From 24d6c2896b2a5b9bd24518231465c0f46b1ba8c0 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:58:34 +0800 Subject: [PATCH 157/168] build: upgrade project to Python 3.14 watchdog 6.0.0 (last release 2024-11-01) ships no cp314 macOS wheel, and uv has no per-package build allowlist under no-build = true, so the preview file watcher moves to watchfiles, which ships cp314 wheels. watchfiles now lives in its own preview dependency group. UV_PYTHON=3.13 is no longer needed on machines that only have 3.14. Co-Authored-By: Claude --- AGENTS.md | 4 --- CLAUDE.md | 4 --- Makefile | 7 ++-- pyproject.toml | 7 ++-- uv.lock | 90 +++++++++++++++++++++++++++----------------------- 5 files changed, 55 insertions(+), 57 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 146958659e..31f45e60e1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,3 @@ An opinionated guide to the best Python frameworks, libraries, tools, and resour - Every keep/drop reason must be verified against current online data at decision time — download counts, repo activity and archived status, PyPI metadata, project docs. Judging tiers — obvious choice vs challenger — also requires WebSearch evidence (adoption trajectory, community sentiment), not download counts alone. Training-data recollections are not evidence; label anything unverifiable as a judgment call. - One entry per commit when adding or deleting entries. Exceptions: a prune sweep is one commit per section, its body listing each removal with its reason; format, wording, or categorization changes may be bundled. - Sponsor placement never influences which projects get listed — see [SPONSORSHIP.md](SPONSORSHIP.md). `website/templates/sponsorship.html` separately defines the sponsorship content on the published website page. - -## Gotchas - -- On machines with only Python 3.14, prefix uv-based make targets with `UV_PYTHON=3.13` — watchdog 6.0.0 ships no 3.14 wheel and the project sets `no-build`. diff --git a/CLAUDE.md b/CLAUDE.md index 1cf71b7332..5da7ad709b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,7 +12,3 @@ An opinionated guide to the best Python frameworks, libraries, tools, and resour - One entry per commit when adding or deleting entries. Exceptions: a prune sweep is one commit per section, its body listing each removal with its reason; format, wording, or categorization changes may be bundled. Cross-section re-homes ride the originating audit's commit (both sides of the move in one diff). - Resources sections are not project entries: out of audit scope, and the website never parses them. - Sponsor placement never influences which projects get listed — see [SPONSORSHIP.md](SPONSORSHIP.md). - -## Gotchas - -- On machines with only Python 3.14, prefix uv-based make targets with `UV_PYTHON=3.13` — watchdog 6.0.0 ships no 3.14 wheel and the project sets `no-build`. diff --git a/Makefile b/Makefile index 6430945e8d..8debe6a969 100644 --- a/Makefile +++ b/Makefile @@ -23,10 +23,7 @@ build: uv run python website/build.py preview: build - uv run watchmedo shell-command \ - --patterns='*.md;*.html;*.css;*.js;*.py' \ - --recursive \ - --wait --drop \ - --command='uv run python website/build.py' \ + uv run watchfiles \ + 'uv run python website/build.py' \ README.md website/templates website/static website/data & \ python -m http.server -b 127.0.0.1 -d website/output/ 8000 diff --git a/pyproject.toml b/pyproject.toml index a1f09178f5..86ee03bf60 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ description = "An opinionated list of awesome Python frameworks, libraries, soft authors = [{ name = "Vinta Chen", email = "vinta.chen@gmail.com" }] readme = "README.md" license = "MIT" -requires-python = ">=3.13" +requires-python = ">=3.14" dependencies = [] [project.urls] @@ -16,11 +16,12 @@ Repository = "https://github.com/vinta/awesome-python" build = ["httpx==0.28.1", "jinja2==3.1.6", "markdown-it-py==4.0.0"] lint = ["ruff==0.15.6", "ty==0.0.33"] test = ["pytest==9.0.3"] +preview = ["watchfiles==1.2.0"] dev = [ { include-group = "build" }, { include-group = "lint" }, { include-group = "test" }, - "watchdog==6.0.0", + { include-group = "preview" }, ] [tool.uv] @@ -34,7 +35,7 @@ only-binary = [":all:"] line-length = 200 [tool.ty.environment] -python-version = "3.13" +python-version = "3.14" root = ["website"] [tool.ty.terminal] diff --git a/uv.lock b/uv.lock index 6ac5047c3f..c7651f9bcd 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,6 @@ version = 1 revision = 3 -requires-python = ">=3.13" +requires-python = ">=3.14" [options] exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. @@ -36,12 +36,15 @@ dev = [ { name = "pytest" }, { name = "ruff" }, { name = "ty" }, - { name = "watchdog" }, + { name = "watchfiles" }, ] lint = [ { name = "ruff" }, { name = "ty" }, ] +preview = [ + { name = "watchfiles" }, +] test = [ { name = "pytest" }, ] @@ -61,12 +64,13 @@ dev = [ { name = "pytest", specifier = "==9.0.3" }, { name = "ruff", specifier = "==0.15.6" }, { name = "ty", specifier = "==0.0.33" }, - { name = "watchdog", specifier = "==6.0.0" }, + { name = "watchfiles", specifier = "==1.2.0" }, ] lint = [ { name = "ruff", specifier = "==0.15.6" }, { name = "ty", specifier = "==0.0.33" }, ] +preview = [{ name = "watchfiles", specifier = "==1.2.0" }] test = [{ name = "pytest", specifier = "==9.0.3" }] [[package]] @@ -172,28 +176,6 @@ version = "3.0.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, - { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, - { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, - { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, - { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, - { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, - { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, - { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, - { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, - { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, - { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, - { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, - { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, - { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, - { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, - { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, - { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, - { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, - { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, - { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, - { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, @@ -320,22 +302,48 @@ wheels = [ ] [[package]] -name = "watchdog" -version = "6.0.0" +name = "watchfiles" +version = "1.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/41/5e1a4bb12aac5f1493fa1bdc11154eca3b258ca4eba65d39c473fe19d8e9/watchfiles-1.2.0.tar.gz", hash = "sha256:c995fba777f1ea992f090f9236e9284cf7a5d1a0130dd5a3d82c598cacd76838", size = 108252, upload-time = "2026-05-18T04:32:04.251Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" }, - { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" }, - { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" }, - { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" }, - { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" }, - { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" }, - { url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077, upload-time = "2024-11-01T14:07:03.893Z" }, - { url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078, upload-time = "2024-11-01T14:07:05.189Z" }, - { url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077, upload-time = "2024-11-01T14:07:06.376Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078, upload-time = "2024-11-01T14:07:07.547Z" }, - { url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065, upload-time = "2024-11-01T14:07:09.525Z" }, - { url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070, upload-time = "2024-11-01T14:07:10.686Z" }, - { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, + { url = "https://files.pythonhosted.org/packages/e7/54/a9c7ea9a82a4ac65e7004c0a03920b5cdd2f9c3b678757d9cd425aa51d53/watchfiles-1.2.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:b8c8358484d5fa12ef34f05b7f4168eaf1932f408725ff6d023c33ec17bd79d4", size = 400205, upload-time = "2026-05-18T04:32:05.153Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5d/c9ab3534374a4a67450696905d6ef16a04405448b8dc52bd752ae50423d4/watchfiles-1.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f04b092229ad2c50126dd3c922c8822e51e605993764a33058d4a791ab42281", size = 392508, upload-time = "2026-05-18T04:30:54.849Z" }, + { url = "https://files.pythonhosted.org/packages/26/ca/1ad30103535cf0cecd7b993e8d50edc5351b1820e38f2d22e3df58962feb/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a7ce236284f002a156f70add88efe5c70879cccbb658be0822c54b1306fc09d", size = 452448, upload-time = "2026-05-18T04:30:53.727Z" }, + { url = "https://files.pythonhosted.org/packages/37/a1/ceee2cdf2afbd715fa07758d39c9859513eae411b23196f7fd039e5feedd/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b9909cc2b48468b575eefa944919e1fe8a36c5849d5c7c168f80a8c1db69398e", size = 459605, upload-time = "2026-05-18T04:30:23.312Z" }, + { url = "https://files.pythonhosted.org/packages/e8/f6/421e30fd1cb3907a84ed92ab3f1983e37ba2dca015e9a894a048418417a2/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a37faaed405c67e28e6be45a1fa4f206ef5a2860f27c237db9fa30704c38242", size = 490757, upload-time = "2026-05-18T04:30:47.358Z" }, + { url = "https://files.pythonhosted.org/packages/41/b0/55ed1b97ed08be7bba6f9a541cac15f2a858e1d74d2b07b6da70a82aab00/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9649193aa27bd9ff2e80ff29bfaa93085496c7a3a377592823cc58b77ee88add", size = 568672, upload-time = "2026-05-18T04:30:38.915Z" }, + { url = "https://files.pythonhosted.org/packages/d1/cf/d8ae8a80dd7bafab395ea7681c10237311bbf34d37704a8c744e7cf31fc7/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e4ff8e37f99cf1da89e255e07c9c4b37c214038c4283707bdec308cb1b0ea1f", size = 464197, upload-time = "2026-05-18T04:30:09.914Z" }, + { url = "https://files.pythonhosted.org/packages/7c/8a/3076c496ca8dafe0e8cd03fcebdfc47be4b1174b4e5b24ff6e396e6b3af2/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:054dc20fd2e3132b4c3883b4a00d72fd6e1f56fdaf89fccd12e8057d74cd74d7", size = 453181, upload-time = "2026-05-18T04:30:14.829Z" }, + { url = "https://files.pythonhosted.org/packages/e5/10/9745e17c98e7b8a86454df0a3c7b5686bd650383f1e9f26e4ebcbd6cc0c0/watchfiles-1.2.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e140ed30ebde76796b686e67c182cff10ea2fbab186fafd1560f74bb5a473a6e", size = 465109, upload-time = "2026-05-18T04:30:28.123Z" }, + { url = "https://files.pythonhosted.org/packages/8f/95/8ef4a95481d3e0cb52d62a06fa6e972e81424be2d9698b91a2fecca9904c/watchfiles-1.2.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:bb7e52ecf68ba46d22df23467b87cffeb2146908aa523ebfe803019618cfda06", size = 630653, upload-time = "2026-05-18T04:31:49.304Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e4/3b3bf36b0f829b50c6ebcb8d031583863c59f923d6a6af3d485e470d0fac/watchfiles-1.2.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:23282a321c8baf9b3a3c4afff673f9fe65eb7fdc2338d765ccad9d3d1916a5ba", size = 657838, upload-time = "2026-05-18T04:31:06.497Z" }, + { url = "https://files.pythonhosted.org/packages/21/b1/6cbbb50c1f3002ab568777d44aa21206dfb8807a840990c4037523b51812/watchfiles-1.2.0-cp314-cp314-win32.whl", hash = "sha256:c0db965c5f79aa49fe672d297cf1febc5ad149b658594944f49a54a2b96270a7", size = 275108, upload-time = "2026-05-18T04:30:06.891Z" }, + { url = "https://files.pythonhosted.org/packages/92/45/190ce6db8dcb4536682cf75d3889ff1a27182a58cb519d343cb6d9ea63d8/watchfiles-1.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:71283b39fd17e5408eb123bd37aeecfd9d54c81fc184421943208aadb879d103", size = 288441, upload-time = "2026-05-18T04:32:12.901Z" }, + { url = "https://files.pythonhosted.org/packages/74/0d/3eae1c2313ab08378431d907c3f8095ecca00f3eda33111cf4f0f2591799/watchfiles-1.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:c5c19526f4e54a00f2666a6c0e9e40d582c09e865055ea7378bf0009aab857b3", size = 280684, upload-time = "2026-05-18T04:31:26.902Z" }, + { url = "https://files.pythonhosted.org/packages/b1/75/fb64e6c25d6b5ca636d03df34ffb1c6e9873303e76d27967e045f8df088f/watchfiles-1.2.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:d73a585accffa5ae39c17264c36ec3166d2fad7000c780f5ef83b2722afb9dd2", size = 398857, upload-time = "2026-05-18T04:32:17.108Z" }, + { url = "https://files.pythonhosted.org/packages/73/4e/9f7adf01754cbf81843722ccfec169d8f26c69778281a302855cecd2ee08/watchfiles-1.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ae99b14c5f21e026e0e9d96f40e07d8570ebee6cafd9d8fc318354606daa7a28", size = 392413, upload-time = "2026-05-18T04:31:07.911Z" }, + { url = "https://files.pythonhosted.org/packages/47/c8/bec626bcc2d69f44b9acb24ce7d60ed7b16b73628eea747fcbd169d8edda/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4429f3b105524a10b72c3a819b091c495d2811d419c1e1e8df773a5a5974f831", size = 452409, upload-time = "2026-05-18T04:31:20.142Z" }, + { url = "https://files.pythonhosted.org/packages/00/b7/b6362068e81e7c556d155a34c35d40ac3ef42d747b06d7f6e5bf58e359c2/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:43d818978d06062d9b22c4fab2ebe44cf5213d42dc8e62bda8c2760cfa2eeb33", size = 458827, upload-time = "2026-05-18T04:32:06.219Z" }, + { url = "https://files.pythonhosted.org/packages/67/f8/9a813fa42afb1e0b4625e75f0479826644d3ee8dc287e093799bc01f390c/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b9f732dc58b2dbe69e464ccf8fff7a03b0dd0be439da4c0720d3558527d3d6b4", size = 490104, upload-time = "2026-05-18T04:31:56.034Z" }, + { url = "https://files.pythonhosted.org/packages/2f/bf/27dfb6094ca4c9aad21298b5525b6c53cb36121ee454331d05161e58d130/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f200104103feb097de4cab8fe4f5dd18a2026934c7dea98c55a2f5fd6d5a33b", size = 571360, upload-time = "2026-05-18T04:31:57.133Z" }, + { url = "https://files.pythonhosted.org/packages/fb/39/44a096d67270ea93df91d33877dbe91fbda3aa4f8ec2edf799d93eda8736/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:63ac26eefbf4af1741247d6fb68b11c49a25b2f7413fbd318a83a12aaa9cf666", size = 464644, upload-time = "2026-05-18T04:30:57.33Z" }, + { url = "https://files.pythonhosted.org/packages/0e/80/c7472203bad6268e3ef1ad260739704847898938ad7ea8b63a5131f46b50/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c4997d4e4a55f0d02b6cde327322daf3a0400e5df6c6b15948994bf72497925", size = 454771, upload-time = "2026-05-18T04:30:48.736Z" }, + { url = "https://files.pythonhosted.org/packages/51/cf/3b10b268b4b7f0fc26e9debb5eef1998b515887840f444cd3ec80c688755/watchfiles-1.2.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:4c887eba18b7945ac73067a8b4a66f21cd46c2539b2bc68588f7be6c7eb6d26b", size = 463494, upload-time = "2026-05-18T04:31:33.826Z" }, + { url = "https://files.pythonhosted.org/packages/3d/3e/a4302545cd589262a0dc7d140e86f7688eba3f9c72776c27f7e23b8864c4/watchfiles-1.2.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:3416ff151bb6b5a8d8d11664974fbef4d9305b9b2957839ab5a270468fd8df30", size = 629383, upload-time = "2026-05-18T04:31:15.596Z" }, + { url = "https://files.pythonhosted.org/packages/db/99/d5649df0a9a410d45b7c882304d0b790903ac9b6e8f2cfd12114e0c6b9f2/watchfiles-1.2.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:0e831a271c035d89789cffc386b6aa1375f39f1cd25eb7ca0997e4970d152fc5", size = 656093, upload-time = "2026-05-18T04:31:58.707Z" }, + { url = "https://files.pythonhosted.org/packages/92/b9/362702539275019a54dd2e94511b31a9b89c5f9e6a21966de7eb692549fc/watchfiles-1.2.0-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:37a6721cdf3f65dbb13aa9503510ccb4451603ac837e44d265d7992a597e1374", size = 400109, upload-time = "2026-05-18T04:31:16.879Z" }, + { url = "https://files.pythonhosted.org/packages/8f/75/71d5ba62db781e5587bded1d944c675374bc4aa37ff33d5018d98e8b6538/watchfiles-1.2.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2b37d10b5a63bd4d87e18472d80fa525bd670586fae62e5dd580452764879b65", size = 392167, upload-time = "2026-05-18T04:31:28.058Z" }, + { url = "https://files.pythonhosted.org/packages/3c/01/c66dd95d0423fe30d31820e2d1d5bda773764131bbb6ac0cb1cf303ac328/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a105bc2283f67e8fbec74253ec2d94925de92ed72c0393f1206bf326b7b7b69", size = 452372, upload-time = "2026-05-18T04:31:00.836Z" }, + { url = "https://files.pythonhosted.org/packages/91/15/2fe99557e72f85627c6a8eed50d889e8d101623e060a22ad75b875cb932d/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5327989a465505f05cfe06f04fa9d0c2fd5432bb243e10e6f012b1bdca3c8579", size = 459596, upload-time = "2026-05-18T04:31:34.96Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/d4acfa0023367428ed48351b3b9b267893037b6cadae55620c61c24bcfd4/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ecb47f183a8025b2aa18b546725c3657e542112ae9c0613a2af79b4fa8d04ad7", size = 490869, upload-time = "2026-05-18T04:31:59.923Z" }, + { url = "https://files.pythonhosted.org/packages/a4/5f/3164cbdce06c9fb95c4f7b9e2f9760b5e2797af43a9ecc317ef42a23a278/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8520a4ab0e37f770afc34459c4f8f7019e153f9124dc101c15538365875d1ab2", size = 571641, upload-time = "2026-05-18T04:32:00.948Z" }, + { url = "https://files.pythonhosted.org/packages/41/e6/85d3731c55e65cd7690f3f803d24c139588aaf863e4bf2148fe7a7fa1a19/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71cd71740ed2c15211ebb237ced4e39a1cdf6f80566e5fe95428da1626f4fde6", size = 464444, upload-time = "2026-05-18T04:30:34.298Z" }, + { url = "https://files.pythonhosted.org/packages/f4/7d/562641012b8b09872742c3b8adf9629ec479fd78f8d68ae4a0c13da8add6/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f88af53d6ddaf72179ef613ddc905e6f4785f712b49b80b3bef9f3525e6194b4", size = 453593, upload-time = "2026-05-18T04:31:23.464Z" }, + { url = "https://files.pythonhosted.org/packages/56/fe/cb8ef3d6f929d14158fdaaad9925985b7310abc9384dcd4d82dd0016fb59/watchfiles-1.2.0-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:cee9d5efd929efdac5f7e58f72b3376f676b64050a91c5b99a7094c5b2317488", size = 465096, upload-time = "2026-05-18T04:31:30.384Z" }, + { url = "https://files.pythonhosted.org/packages/25/91/80908e835e100527a9267147b08c0eee1fa6ab0ffec15edc04d1d44885f7/watchfiles-1.2.0-cp315-cp315-musllinux_1_1_aarch64.whl", hash = "sha256:b718bf356bbc15e559bd8ef41782b573b8ae0e3f177ab244b440568d7ea02cfb", size = 630638, upload-time = "2026-05-18T04:30:49.89Z" }, + { url = "https://files.pythonhosted.org/packages/46/4b/95ab2f256bb4af3cb2eb23b9317bda984ee6e0f11733a5c004a6c95b06e3/watchfiles-1.2.0-cp315-cp315-musllinux_1_1_x86_64.whl", hash = "sha256:922c0e019fe68b3ae392965a766b02a71ba1168c932cebc3733cd52c5fe5b377", size = 657684, upload-time = "2026-05-18T04:31:32.027Z" }, ] From 0d13cd27f1ffdb457481a84bb88857d505e70d81 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 16:59:09 +0800 Subject: [PATCH 158/168] build: use >= floors instead of == pins for dependency groups Exact reproducibility already lives in uv.lock via 'uv sync --locked', so == in pyproject.toml only duplicates the lockfile and blocks 'uv lock --upgrade'. Locked versions are unchanged. Co-Authored-By: Claude --- pyproject.toml | 8 ++++---- uv.lock | 28 ++++++++++++++-------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 86ee03bf60..30ce8fc591 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,10 +13,10 @@ Homepage = "https://awesome-python.com/" Repository = "https://github.com/vinta/awesome-python" [dependency-groups] -build = ["httpx==0.28.1", "jinja2==3.1.6", "markdown-it-py==4.0.0"] -lint = ["ruff==0.15.6", "ty==0.0.33"] -test = ["pytest==9.0.3"] -preview = ["watchfiles==1.2.0"] +build = ["httpx>=0.28.1", "jinja2>=3.1.6", "markdown-it-py>=4.0.0"] +lint = ["ruff>=0.15.6", "ty>=0.0.33"] +test = ["pytest>=9.0.3"] +preview = ["watchfiles>=1.2.0"] dev = [ { include-group = "build" }, { include-group = "lint" }, diff --git a/uv.lock b/uv.lock index c7651f9bcd..a3d6793cb8 100644 --- a/uv.lock +++ b/uv.lock @@ -53,25 +53,25 @@ test = [ [package.metadata.requires-dev] build = [ - { name = "httpx", specifier = "==0.28.1" }, - { name = "jinja2", specifier = "==3.1.6" }, - { name = "markdown-it-py", specifier = "==4.0.0" }, + { name = "httpx", specifier = ">=0.28.1" }, + { name = "jinja2", specifier = ">=3.1.6" }, + { name = "markdown-it-py", specifier = ">=4.0.0" }, ] dev = [ - { name = "httpx", specifier = "==0.28.1" }, - { name = "jinja2", specifier = "==3.1.6" }, - { name = "markdown-it-py", specifier = "==4.0.0" }, - { name = "pytest", specifier = "==9.0.3" }, - { name = "ruff", specifier = "==0.15.6" }, - { name = "ty", specifier = "==0.0.33" }, - { name = "watchfiles", specifier = "==1.2.0" }, + { name = "httpx", specifier = ">=0.28.1" }, + { name = "jinja2", specifier = ">=3.1.6" }, + { name = "markdown-it-py", specifier = ">=4.0.0" }, + { name = "pytest", specifier = ">=9.0.3" }, + { name = "ruff", specifier = ">=0.15.6" }, + { name = "ty", specifier = ">=0.0.33" }, + { name = "watchfiles", specifier = ">=1.2.0" }, ] lint = [ - { name = "ruff", specifier = "==0.15.6" }, - { name = "ty", specifier = "==0.0.33" }, + { name = "ruff", specifier = ">=0.15.6" }, + { name = "ty", specifier = ">=0.0.33" }, ] -preview = [{ name = "watchfiles", specifier = "==1.2.0" }] -test = [{ name = "pytest", specifier = "==9.0.3" }] +preview = [{ name = "watchfiles", specifier = ">=1.2.0" }] +test = [{ name = "pytest", specifier = ">=9.0.3" }] [[package]] name = "certifi" From e9329d4d1e2497f7b14c9885004419b343a03421 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 17:50:33 +0800 Subject: [PATCH 159/168] fix: correct hydra-core repo URL to facebookresearch/hydra The entry linked hydra-ecosystem/hydra, an unrelated W3C Hydra API toolkit, while the entry name and description describe facebookresearch's Hydra configuration framework, mixing the wrong repo's stars with the right package's identity. Found during the downloads-column identity sweep. Co-Authored-By: Claude --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a001b8f0e6..f510f538e1 100644 --- a/README.md +++ b/README.md @@ -1085,7 +1085,7 @@ _Libraries for storing and parsing configuration options._ - [configparser](https://docs.python.org/3/library/configparser.html) - (Python standard library) INI file parser. - [python-dotenv](https://github.com/theskumar/python-dotenv) - Reads key-value pairs from a `.env` file and sets them as environment variables. - [pydantic-settings](https://github.com/pydantic/pydantic-settings) - Settings management using Pydantic models with validation, loading from environment variables and secrets files. -- [hydra-core](https://github.com/hydra-ecosystem/hydra) - Hydra is a framework for elegantly configuring complex applications. +- [hydra-core](https://github.com/facebookresearch/hydra) - Hydra is a framework for elegantly configuring complex applications. - [dynaconf](https://github.com/dynaconf/dynaconf) - Dynaconf is a configuration manager with plugins for Django, Flask and FastAPI. **Security** From b440e64cd0a5cd75ebff0029b250c43b4137d70f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 17:51:11 +0800 Subject: [PATCH 160/168] fix: resolve PyPI download counts through curated package overrides A pypi.org identity sweep of all 438 cached rows (project_urls/home_page vs entry GitHub URL) found download counts were looked up by README display name, so entries whose name differs from the canonical package silently measured squatters or dead predecessors: pytorch measured a squatter (169,737/mo vs torch's 94M), jinja measured Jinja1 (3,168 vs jinja2's 736M), django-rest-framework a dead alias package (real: djangorestframework), django-rules an abandoned fork (real: rules), strawberry an unrelated bookmarking service (real: strawberry-graphql), devpi a deprecated metapackage (mapped to devpi-server). New curated website/data/pypi_name_overrides.json maps normalized README name to the real package, or null for projects not pip-installable whose name is squatted or a relic (cpython, pyenv, renpy, python-patterns, winpython); also maps mem0 to mem0ai, fasthtml to python-fasthtml, and playwright-python to playwright. All three fetch scripts resolve names through it; the clickpy TSV cache gains a package column recording what each row actually measured. .gitignore switches website/data/ to website/data/* with a negation so the curated overrides file is tracked while caches stay ignored. Co-Authored-By: Claude --- .gitignore | 3 +- website/data/pypi_name_overrides.json | 16 +++++++ website/fetch_pypi_downloads_via_bigquery.py | 16 +++++-- website/fetch_pypi_downloads_via_clickpy.py | 44 ++++++++++++++------ website/fetch_pypi_downloads_via_pepy.py | 13 ++++-- 5 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 website/data/pypi_name_overrides.json diff --git a/.gitignore b/.gitignore index 1f2c6f1e01..ba30760958 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,8 @@ __pycache__/ # website website/output/ -website/data/ +website/data/* +!website/data/pypi_name_overrides.json # agents .playwright-cli/ diff --git a/website/data/pypi_name_overrides.json b/website/data/pypi_name_overrides.json new file mode 100644 index 0000000000..47a400a09c --- /dev/null +++ b/website/data/pypi_name_overrides.json @@ -0,0 +1,16 @@ +{ + "cpython": null, + "devpi": "devpi-server", + "django-rest-framework": "djangorestframework", + "django-rules": "rules", + "fasthtml": "python-fasthtml", + "jinja": "jinja2", + "mem0": "mem0ai", + "playwright-python": "playwright", + "pyenv": null, + "python-patterns": null, + "pytorch": "torch", + "renpy": null, + "strawberry": "strawberry-graphql", + "winpython": null +} diff --git a/website/fetch_pypi_downloads_via_bigquery.py b/website/fetch_pypi_downloads_via_bigquery.py index 21f69479a1..e8b5bbfc57 100644 --- a/website/fetch_pypi_downloads_via_bigquery.py +++ b/website/fetch_pypi_downloads_via_bigquery.py @@ -3,7 +3,8 @@ Queries the canonical source ClickPy mirrors — `bigquery-public-data.pypi.file_downloads` via the `bq` CLI — and prints -namecount TSV to stdout. Maintainer-local (needs a personal GCP +namecount TSV to stdout. Names resolve through +data/pypi_name_overrides.json, matching the cache sweep. Maintainer-local (needs a personal GCP account) and print-only: data/pypi_downloads.tsv is written solely by fetch_pypi_downloads_via_clickpy.py. @@ -27,7 +28,7 @@ import sys from json import loads -from fetch_pypi_downloads_via_clickpy import normalize +from fetch_pypi_downloads_via_clickpy import resolve MAX_BYTES_BILLED = 400_000_000_000 @@ -59,7 +60,16 @@ def fetch_bigquery(names: list[str], dry_run: bool) -> dict[str, int]: def main() -> None: dry_run = "--dry-run" in sys.argv - names = sorted({normalize(arg) for arg in sys.argv[1:] if arg != "--dry-run"}) + names = set() + for arg in sys.argv[1:]: + if arg == "--dry-run": + continue + pkg = resolve(arg) + if pkg is None: + print(f"{arg}: not pip-installable per pypi_name_overrides.json, skipping", file=sys.stderr) + else: + names.add(pkg) + names = sorted(names) if not names: print("Usage: python fetch_pypi_downloads_via_bigquery.py [--dry-run] NAME [NAME ...]", file=sys.stderr) sys.exit(1) diff --git a/website/fetch_pypi_downloads_via_clickpy.py b/website/fetch_pypi_downloads_via_clickpy.py index 1e7c1a262b..6934dc0133 100644 --- a/website/fetch_pypi_downloads_via_clickpy.py +++ b/website/fetch_pypi_downloads_via_clickpy.py @@ -13,20 +13,24 @@ This script is the sole writer of data/pypi_downloads.tsv and rewrites it from scratch each run, so entries removed from README.md drop out naturally; names with no PyPI rows are written as NOT_FOUND. Counts are -looked up by README display name: when the display name differs from the -canonical PyPI package, the row silently measures the wrong package (a -squatter or a dead predecessor) — verify identity at -pypi.org/pypi/{name}/json before citing a count. The file -starts with a header row (name, downloads, fetched_at) and every row -carries the sweep date: a cache fetched within the last 7 days is current -enough for audit verdicts, so only re-run when older. Cross-checks -against other sources (fetch_pypi_downloads_via_bigquery.py, +looked up by README display name; when the display name differs from the +canonical PyPI package (a squatter or a dead predecessor would be +measured otherwise), add the mapping to the curated +data/pypi_name_overrides.json — normalized README name to the real +package, or null for projects that are not pip-installable so their +row is never queried. The file starts with a header row (name, package, +downloads, fetched_at) — package is the PyPI package the row actually +measured ("-" for null overrides) — and every row carries the sweep +date: a cache fetched within the last 7 days is current enough for +audit verdicts, so only re-run when older. Cross-checks against other +sources (fetch_pypi_downloads_via_bigquery.py, fetch_pypi_downloads_via_pepy.py) print to stdout and never touch the cache. Usage: python fetch_pypi_downloads_via_clickpy.py """ +import json import re from datetime import date from pathlib import Path @@ -36,6 +40,7 @@ DATA_DIR = Path(__file__).parent / "data" OUT_FILE = DATA_DIR / "pypi_downloads.tsv" +OVERRIDES_FILE = DATA_DIR / "pypi_name_overrides.json" README_PATH = Path(__file__).parent.parent / "README.md" CLICKPY_URL = "https://sql-clickhouse.clickhouse.com/?user=demo" @@ -47,6 +52,16 @@ def normalize(name: str) -> str: return re.sub(r"[-_.]+", "-", name.lower()) +def load_overrides() -> dict[str, str | None]: + return json.loads(OVERRIDES_FILE.read_text()) + + +def resolve(name: str) -> str | None: + """Map a README display name to the PyPI package to measure. None = not pip-installable.""" + normalized = normalize(name) + return load_overrides().get(normalized, normalized) + + def collect_names(readme_text: str) -> list[str]: names = set() for group in parse_readme(readme_text): @@ -73,12 +88,15 @@ def fetch_clickpy(names: list[str]) -> dict[str, int]: def main() -> None: names = collect_names(README_PATH.read_text()) - print(f"Querying {len(names)} package names...") - counts = fetch_clickpy(names) + overrides = load_overrides() + packages = {name: overrides.get(name, name) for name in names} + query_names = sorted({pkg for pkg in packages.values() if pkg}) + print(f"Querying {len(query_names)} package names...") + counts = fetch_clickpy(query_names) fetched_at = date.today().isoformat() - rows = "\n".join(f"{name}\t{counts.get(name, 'NOT_FOUND')}\t{fetched_at}" for name in names) - OUT_FILE.write_text(f"name\tdownloads\tfetched_at\n{rows}\n") - print(f"Done. {len(counts)}/{len(names)} names found on PyPI. Cached to {OUT_FILE}") + rows = "\n".join(f"{name}\t{pkg or '-'}\t{counts.get(pkg, 'NOT_FOUND') if pkg else 'NOT_FOUND'}\t{fetched_at}" for name, pkg in packages.items()) + OUT_FILE.write_text(f"name\tpackage\tdownloads\tfetched_at\n{rows}\n") + print(f"Done. {len(counts)}/{len(query_names)} names found on PyPI. Cached to {OUT_FILE}") if __name__ == "__main__": diff --git a/website/fetch_pypi_downloads_via_pepy.py b/website/fetch_pypi_downloads_via_pepy.py index 998f260f90..55eb75938e 100644 --- a/website/fetch_pypi_downloads_via_pepy.py +++ b/website/fetch_pypi_downloads_via_pepy.py @@ -7,7 +7,8 @@ (use fetch_pypi_downloads_via_clickpy.py for bulk). Reads PEPY_TECH_API_KEY from the environment, falling back to the repo-root .env. The v2 endpoint returns ~90 days of per-day per-version counts; this script sums the most recent -30 days present in the response across all versions. pepy counts include +30 days present in the response across all versions. Names resolve +through data/pypi_name_overrides.json, matching the cache sweep. pepy counts include mirror/CI traffic (CI filtering is a paid pepy feature), matching the ClickPy/BigQuery figures; pypistats.org excludes mirrors, so never mix the two in one comparison. Results print to stdout as TSV and are not @@ -22,7 +23,7 @@ from pathlib import Path import httpx -from fetch_pypi_downloads_via_clickpy import normalize +from fetch_pypi_downloads_via_clickpy import resolve ENV_FILE = Path(__file__).parent.parent / ".env" PEPY_URL = "https://api.pepy.tech/api/v2/projects/{name}" @@ -51,7 +52,13 @@ def main() -> None: if len(sys.argv) < 2: print("Usage: python fetch_pypi_downloads_via_pepy.py NAME [NAME ...]", file=sys.stderr) sys.exit(1) - names = [normalize(name) for name in sys.argv[1:]] + names = [] + for arg in sys.argv[1:]: + pkg = resolve(arg) + if pkg is None: + print(f"{arg}: not pip-installable per pypi_name_overrides.json, skipping", file=sys.stderr) + else: + names.append(pkg) with httpx.Client(headers={"X-API-Key": load_api_key()}, timeout=30) as client: for i, name in enumerate(names): if i: From cc804b1de2b85e7dcc46f04e4c334f6d37d4cbca Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 17:52:04 +0800 Subject: [PATCH 161/168] feat: add Downloads/Month column to website table Sourced from website/data/pypi_downloads.tsv the same way github_stars.json feeds the stars column. The new sortable column sits between GitHub Stars and Last Commit on the homepage and category pages, formatted with thousands separators like stars, with an em dash when no PyPI data exists. Rows are matched by normalized README display name; Built-in entries never show counts since same-named PyPI packages are stdlib backports (e.g. the asyncio package). Below 960px the column hides and the count moves into the expand row, mirroring the existing Last Commit treatment. main.js gains the downloads sort branch and URL param. The deploy workflow fetches the TSV via the new make fetch_pypi_downloads target with a daily actions/cache fallback, mirroring the stars fetch, but non-fatal: the column degrades to dashes when the fetch fails, unlike stars which the build requires. Co-Authored-By: Claude --- .github/workflows/deploy-website.yml | 19 +++++++++++ Makefile | 3 ++ website/build.py | 23 +++++++++++++ website/static/main.js | 13 +++++++- website/static/style.css | 17 ++++++++-- website/templates/category.html | 15 +++++++-- website/templates/index.html | 15 +++++++-- website/tests/test_build.py | 49 ++++++++++++++++++++++++++++ 8 files changed, 146 insertions(+), 8 deletions(-) diff --git a/.github/workflows/deploy-website.yml b/.github/workflows/deploy-website.yml index dd748bb563..0c23761c62 100644 --- a/.github/workflows/deploy-website.yml +++ b/.github/workflows/deploy-website.yml @@ -71,6 +71,25 @@ jobs: fi python -m json.tool website/data/github_stars.json > /dev/null + - name: Restore PyPI download data cache + uses: actions/cache/restore@v4 + with: + path: website/data/pypi_downloads.tsv + key: pypi-downloads-${{ steps.date.outputs.today }} + restore-keys: pypi-downloads- + + - name: Fetch PyPI downloads + id: fetch-downloads + continue-on-error: true + run: make fetch_pypi_downloads + + - name: Save PyPI download data cache + if: steps.fetch-downloads.outcome == 'success' + uses: actions/cache/save@v4 + with: + path: website/data/pypi_downloads.tsv + key: pypi-downloads-${{ steps.date.outputs.today }} + - name: Build website run: make build diff --git a/Makefile b/Makefile index 8debe6a969..5a07ad9119 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,9 @@ install: fetch_github_stars: uv run python website/fetch_github_stars.py +fetch_pypi_downloads: + uv run python website/fetch_pypi_downloads_via_clickpy.py + test: uv run pytest website/tests/ -v diff --git a/website/build.py b/website/build.py index 347c4fb022..cba524faaf 100644 --- a/website/build.py +++ b/website/build.py @@ -11,6 +11,7 @@ from pathlib import Path from typing import TypedDict +from fetch_pypi_downloads_via_clickpy import normalize from jinja2 import Environment, FileSystemLoader from readme_parser import AlsoSee, ParsedGroup, ParsedSection, parse_readme, parse_sponsors, slugify @@ -52,6 +53,7 @@ class TemplateEntry(TypedDict): groups: list[str] subcategories: list[TemplateSubcategory] stars: int | None + downloads: int | None owner: str | None last_commit_at: str | None source_type: str | None @@ -96,6 +98,22 @@ def load_stars(path: Path) -> dict[str, dict]: return {} +def load_downloads(path: Path) -> dict[str, int]: + """Load last-30-day download counts from the TSV cache, keyed by normalized README name. + + Columns: name, package, downloads, fetched_at. Skips the header and + NOT_FOUND rows. Returns empty dict if the file doesn't exist. + """ + if not path.exists(): + return {} + downloads: dict[str, int] = {} + for line in path.read_text(encoding="utf-8").splitlines()[1:]: + parts = line.split("\t") + if len(parts) >= 3 and parts[2].isdigit(): + downloads[parts[0]] = int(parts[2]) + return downloads + + def sort_entries(entries: Sequence[TemplateEntry]) -> list[TemplateEntry]: """Sort entries by stars descending, then name ascending. @@ -481,6 +499,7 @@ def extract_entries( groups=[], subcategories=[], stars=None, + downloads=None, owner=None, last_commit_at=None, source_type=detect_source_type(entry["url"]), @@ -535,6 +554,7 @@ def build(repo_root: Path) -> None: build_date = datetime.now(UTC) stars_data = load_stars(website / "data" / "github_stars.json") + downloads_data = load_downloads(website / "data" / "pypi_downloads.tsv") repo_self = stars_data.get("vinta/awesome-python", {}) repo_stars = None @@ -551,6 +571,9 @@ def build(repo_root: Path) -> None: entry["stars"] = sd["stars"] entry["owner"] = sd["owner"] entry["last_commit_at"] = sd.get("last_commit_at", "") + # Built-in entries would hit same-named PyPI backports (e.g. asyncio), not the stdlib. + if entry.get("source_type") != "Built-in": + entry["downloads"] = downloads_data.get(normalize(entry["name"])) entries = sort_entries(entries) category_urls = {cat["name"]: category_path(cat) for cat in categories} diff --git a/website/static/main.js b/website/static/main.js index d5b337b341..073bb6c4b0 100644 --- a/website/static/main.js +++ b/website/static/main.js @@ -238,6 +238,14 @@ function getSortValue(row, col) { const num = parseInt(text, 10); return isNaN(num) ? -1 : num; } + if (col === "downloads") { + const text = row + .querySelector(".col-downloads") + .textContent.trim() + .replace(/,/g, ""); + const num = parseInt(text, 10); + return isNaN(num) ? -1 : num; + } if (col === "commit-time") { const attr = row.querySelector(".col-commit").getAttribute("data-commit"); return attr ? new Date(attr).getTime() : 0; @@ -467,7 +475,10 @@ if (backToTop) { const order = params.get("order"); if (q && searchInput) searchInput.value = q; if ( - (sort === "name" || sort === "stars" || sort === "commit-time") && + (sort === "name" || + sort === "stars" || + sort === "downloads" || + sort === "commit-time") && (order === "desc" || order === "asc") ) { activeSort = { col: sort, order: order }; diff --git a/website/static/style.css b/website/static/style.css index 93056570aa..1cd3a9f9f6 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -893,6 +893,14 @@ th[data-sort].sort-asc::after { letter-spacing: 0.02em; } +.col-downloads { + width: 9.5rem; + text-align: right; + white-space: nowrap; + font-variant-numeric: tabular-nums; + color: var(--ink-soft); +} + .col-commit { width: 9rem; white-space: nowrap; @@ -1041,7 +1049,8 @@ th[data-sort].sort-asc::after { color: var(--line-strong); } -.expand-commit { +.expand-commit, +.expand-downloads { display: none; } @@ -1606,11 +1615,13 @@ th[data-sort].sort-asc::after { justify-self: start; } - .col-commit { + .col-commit, + .col-downloads { display: none; } - .expand-commit { + .expand-commit, + .expand-downloads { display: inline; } diff --git a/website/templates/category.html b/website/templates/category.html index 6e4b03e792..51542767e2 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -120,6 +120,9 @@

Results

+ + + @@ -156,6 +159,10 @@

Results

>{{ entry.source_type }}{% else %}—{% endif %} + + {% if entry.downloads is not none %}{{ + "{:,}".format(entry.downloads) }}{% else %}—{% endif %} + Results {% if entry.description %} - +
{{ entry.description | safe }}
{% endif %} - +
{% if entry.also_see %}
@@ -249,6 +256,10 @@

Results

>{% endif %} {% if entry.downloads is not none %}/{{ + "{:,}".format(entry.downloads) }} downloads/month{% endif %}
diff --git a/website/templates/index.html b/website/templates/index.html index e7f1c9ea56..dc20049fca 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -171,6 +171,9 @@

Results

+ + + @@ -207,6 +210,10 @@

Results

>{{ entry.source_type }}{% else %}—{% endif %} + + {% if entry.downloads is not none %}{{ + "{:,}".format(entry.downloads) }}{% else %}—{% endif %} + Results {% if entry.description %} - +
{{ entry.description | safe }}
{% endif %} - +
{% if entry.description %}
{{ entry.description | safe }}
@@ -298,6 +305,10 @@

Results

>{% endif %} {% if entry.downloads is not none %}/{{ + "{:,}".format(entry.downloads) }} downloads/month{% endif %}
diff --git a/website/tests/test_build.py b/website/tests/test_build.py index 0af6c0de2c..3b417b2409 100644 --- a/website/tests/test_build.py +++ b/website/tests/test_build.py @@ -17,6 +17,7 @@ detect_source_type, extract_entries, extract_github_repo, + load_downloads, load_stars, sort_entries, subcategory_path, @@ -429,6 +430,40 @@ def test_build_with_stars_sorts_by_stars(self, tmp_path): # Expand content present assert "expand-content" in html + def test_build_with_downloads_renders_column(self, tmp_path): + readme = textwrap.dedent("""\ + # T + + ## Projects + + ## Stuff + + - [My-Lib](https://github.com/org/mylib) - On PyPI. + - [no-pypi](https://example.com/none) - Not on PyPI. + - [asyncio](https://docs.python.org/3/library/asyncio.html) - Built-in. + + # Contributing + + Done. + """) + (tmp_path / "README.md").write_text(readme, encoding="utf-8") + self._copy_real_templates(tmp_path) + + data_dir = tmp_path / "website" / "data" + data_dir.mkdir(parents=True) + # Keyed by normalized README display name, like fetch_pypi_downloads_via_clickpy.py writes it + (data_dir / "pypi_downloads.tsv").write_text( + "name\tpackage\tdownloads\tfetched_at\nasyncio\tasyncio\t26305454\t2026-08-16\nmy-lib\tmy-lib\t1234567\t2026-08-16\n", + encoding="utf-8", + ) + + build(tmp_path) + + html = (tmp_path / "website" / "output" / "index.html").read_text(encoding="utf-8") + assert "1,234,567" in html + # Built-in entries never show PyPI counts: the asyncio row is the backport package + assert "26,305,454" not in html + def test_build_fails_when_group_and_category_slug_collide(self, tmp_path): readme = textwrap.dedent("""\ # T @@ -974,6 +1009,7 @@ def _template_entry(name: str, stars: int | None, source_type: str | None = None groups=[], subcategories=[], stars=stars, + downloads=None, owner=None, last_commit_at=None, source_type=source_type, @@ -1199,3 +1235,16 @@ def test_preserves_lines_without_trailing_newline(self): markdown = "- [foo](https://github.com/owner/foo) - A foo." stars = {"owner/foo": {"stars": 5, "owner": "owner"}} assert annotate_entries_with_stars(markdown, stars) == ("- [foo](https://github.com/owner/foo) - A foo. (5 GitHub stars)") + + +class TestLoadDownloads: + def test_parses_tsv_and_skips_not_found(self, tmp_path): + tsv = tmp_path / "pypi_downloads.tsv" + tsv.write_text( + "name\tpackage\tdownloads\tfetched_at\naiohttp\taiohttp\t649105404\t2026-08-16\npytorch\ttorch\t50000000\t2026-08-16\ndead-pkg\t-\tNOT_FOUND\t2026-08-16\n", + encoding="utf-8", + ) + assert load_downloads(tsv) == {"aiohttp": 649105404, "pytorch": 50000000} + + def test_missing_file_returns_empty(self, tmp_path): + assert load_downloads(tmp_path / "nope.tsv") == {} From f3ff733fd7ac97e888df5e48ceb2e288140995df Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 18:54:58 +0800 Subject: [PATCH 162/168] fix: add three more PyPI name remaps for NOT_FOUND triage autobahn-python publishes as autobahn (7.1M/mo), pangu-py as pangu, and strawberry-django as strawberry-graphql-django (1.5M/mo). httpx.URL is left unmapped deliberately since it's a class within the httpx package, not a package of its own. Co-Authored-By: Claude --- website/data/pypi_name_overrides.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/data/pypi_name_overrides.json b/website/data/pypi_name_overrides.json index 47a400a09c..78e691c13b 100644 --- a/website/data/pypi_name_overrides.json +++ b/website/data/pypi_name_overrides.json @@ -1,4 +1,5 @@ { + "autobahn-python": "autobahn", "cpython": null, "devpi": "devpi-server", "django-rest-framework": "djangorestframework", @@ -6,11 +7,13 @@ "fasthtml": "python-fasthtml", "jinja": "jinja2", "mem0": "mem0ai", + "pangu-py": "pangu", "playwright-python": "playwright", "pyenv": null, "python-patterns": null, "pytorch": "torch", "renpy": null, "strawberry": "strawberry-graphql", + "strawberry-django": "strawberry-graphql-django", "winpython": null } From fcfc65df00d88c2264c6a2106bcf4400e8c1ff7b Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 18:57:13 +0800 Subject: [PATCH 163/168] data: record all remaining NOT_FOUND names as explicit null overrides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every queried name now resolves 447/447. Adds 23 explicit null overrides so squatters can never silently attach a PyPI number to these names later: stdlib-named entries (concurrent-futures, difflib, mimetypes, sqlite3, tkinter, tomllib, zoneinfo), interpreters (micropython, pypy), monorepo umbrellas (azure-sdk-for-python, google-cloud-python), self-hosted or distro-installed projects (odoo, cloud-init, warehouse), GitHub-only projects (thealgorithms, geodjango, django-db-models, django-ai-plugins, graphify, sentry-skills, social-engineer-toolkit, trailofbits-skills), and httpx-url (a class within httpx, not a package). Caveat: graphify and django-ai-plugins are young projects that may legitimately publish to PyPI later — flip their null to a remap during a future audit if they do. Co-Authored-By: Claude --- website/data/pypi_name_overrides.json | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/website/data/pypi_name_overrides.json b/website/data/pypi_name_overrides.json index 78e691c13b..5ec7958a40 100644 --- a/website/data/pypi_name_overrides.json +++ b/website/data/pypi_name_overrides.json @@ -1,19 +1,42 @@ { "autobahn-python": "autobahn", + "azure-sdk-for-python": null, + "cloud-init": null, + "concurrent-futures": null, "cpython": null, "devpi": "devpi-server", + "difflib": null, + "django-ai-plugins": null, + "django-db-models": null, "django-rest-framework": "djangorestframework", "django-rules": "rules", "fasthtml": "python-fasthtml", + "geodjango": null, + "google-cloud-python": null, + "graphify": null, + "httpx-url": null, "jinja": "jinja2", "mem0": "mem0ai", + "micropython": null, + "mimetypes": null, + "odoo": null, "pangu-py": "pangu", "playwright-python": "playwright", "pyenv": null, + "pypy": null, "python-patterns": null, "pytorch": "torch", "renpy": null, + "sentry-skills": null, + "social-engineer-toolkit": null, + "sqlite3": null, "strawberry": "strawberry-graphql", "strawberry-django": "strawberry-graphql-django", - "winpython": null + "thealgorithms": null, + "tkinter": null, + "tomllib": null, + "trailofbits-skills": null, + "warehouse": null, + "winpython": null, + "zoneinfo": null } From b841db68ba4c032a4896a3477905951d5b6d8613 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 19:08:55 +0800 Subject: [PATCH 164/168] refactor: make pypi_name_overrides.json entries self-documenting Every entry is now {"package": str|null, "reason": str|null} instead of a bare string/null. Reasons are required for null packages, explaining why the name must never be queried (squatted name, stdlib module, monorepo umbrella, GitHub-only project, and so on). Reasons are optional for remaps and kept only on the six non-obvious ones: pytorch (squatter), jinja (jinja is Jinja1), strawberry (unrelated bookmarking service), django-rules (abandoned fork), django-rest-framework (dead alias), and devpi (deprecated metapackage); plain publishes-as-X remaps get a null reason. load_overrides() in the clickpy fetcher now extracts the package field from each entry; resolve() and the pepy/bigquery cross-check scripts are unchanged since they consume load_overrides()'s output. Co-Authored-By: Claude --- website/data/pypi_name_overrides.json | 80 ++++++++++----------- website/fetch_pypi_downloads_via_clickpy.py | 15 ++-- 2 files changed, 51 insertions(+), 44 deletions(-) diff --git a/website/data/pypi_name_overrides.json b/website/data/pypi_name_overrides.json index 5ec7958a40..8c8a5f95f6 100644 --- a/website/data/pypi_name_overrides.json +++ b/website/data/pypi_name_overrides.json @@ -1,42 +1,42 @@ { - "autobahn-python": "autobahn", - "azure-sdk-for-python": null, - "cloud-init": null, - "concurrent-futures": null, - "cpython": null, - "devpi": "devpi-server", - "difflib": null, - "django-ai-plugins": null, - "django-db-models": null, - "django-rest-framework": "djangorestframework", - "django-rules": "rules", - "fasthtml": "python-fasthtml", - "geodjango": null, - "google-cloud-python": null, - "graphify": null, - "httpx-url": null, - "jinja": "jinja2", - "mem0": "mem0ai", - "micropython": null, - "mimetypes": null, - "odoo": null, - "pangu-py": "pangu", - "playwright-python": "playwright", - "pyenv": null, - "pypy": null, - "python-patterns": null, - "pytorch": "torch", - "renpy": null, - "sentry-skills": null, - "social-engineer-toolkit": null, - "sqlite3": null, - "strawberry": "strawberry-graphql", - "strawberry-django": "strawberry-graphql-django", - "thealgorithms": null, - "tkinter": null, - "tomllib": null, - "trailofbits-skills": null, - "warehouse": null, - "winpython": null, - "zoneinfo": null + "autobahn-python": { "package": "autobahn", "reason": null }, + "azure-sdk-for-python": { "package": null, "reason": "monorepo umbrella; ships as many azure-* packages, no single package represents it" }, + "cloud-init": { "package": null, "reason": "installed via distro images, not pip" }, + "concurrent-futures": { "package": null, "reason": "stdlib module" }, + "cpython": { "package": null, "reason": "not pip-installable; the cpython PyPI name was squatted" }, + "devpi": { "package": "devpi-server", "reason": "devpi is a deprecated metapackage; the server package carries real usage" }, + "difflib": { "package": null, "reason": "stdlib module" }, + "django-ai-plugins": { "package": null, "reason": "GitHub-only so far; young project, remap if it publishes" }, + "django-db-models": { "package": null, "reason": "part of Django, not a package" }, + "django-rest-framework": { "package": "djangorestframework", "reason": "django-rest-framework is a dead alias package" }, + "django-rules": { "package": "rules", "reason": "PyPI django-rules is an abandoned unrelated fork; dfunckt's project publishes as rules" }, + "fasthtml": { "package": "python-fasthtml", "reason": null }, + "geodjango": { "package": null, "reason": "part of Django (django.contrib.gis), not a package" }, + "google-cloud-python": { "package": null, "reason": "monorepo umbrella; ships as many google-cloud-* packages" }, + "graphify": { "package": null, "reason": "GitHub-only so far; young project, remap if it publishes" }, + "httpx-url": { "package": null, "reason": "class in the httpx package, not a package" }, + "jinja": { "package": "jinja2", "reason": "PyPI jinja is Jinja1; current releases publish as jinja2" }, + "mem0": { "package": "mem0ai", "reason": null }, + "micropython": { "package": null, "reason": "interpreter distributed as firmware builds, not pip" }, + "mimetypes": { "package": null, "reason": "stdlib module" }, + "odoo": { "package": null, "reason": "self-hosted suite installed from odoo.com, not pip" }, + "pangu-py": { "package": "pangu", "reason": null }, + "playwright-python": { "package": "playwright", "reason": null }, + "pyenv": { "package": null, "reason": "installed via git/homebrew; PyPI pyenv is a defunct shim" }, + "pypy": { "package": null, "reason": "interpreter distributed via pypy.org, not pip" }, + "python-patterns": { "package": null, "reason": "reference repo, not a package; PyPI name held by unrelated 2012 project" }, + "pytorch": { "package": "torch", "reason": "PyPI pytorch is a squatter; real package is torch" }, + "renpy": { "package": null, "reason": "distributed via renpy.org; PyPI name was squatted, now 404" }, + "sentry-skills": { "package": null, "reason": "agent skills repo, not a package" }, + "social-engineer-toolkit": { "package": null, "reason": "GitHub-only, installed from source" }, + "sqlite3": { "package": null, "reason": "stdlib module" }, + "strawberry": { "package": "strawberry-graphql", "reason": "PyPI strawberry is an unrelated bookmarking service" }, + "strawberry-django": { "package": "strawberry-graphql-django", "reason": null }, + "thealgorithms": { "package": null, "reason": "educational monorepo, not a package" }, + "tkinter": { "package": null, "reason": "stdlib module" }, + "tomllib": { "package": null, "reason": "stdlib module" }, + "trailofbits-skills": { "package": null, "reason": "agent skills repo, not a package" }, + "warehouse": { "package": null, "reason": "the PyPI server itself; deployed, not pip-installed" }, + "winpython": { "package": null, "reason": "distribution with its own installer; PyPI name is a 2012 relic" }, + "zoneinfo": { "package": null, "reason": "stdlib module" } } diff --git a/website/fetch_pypi_downloads_via_clickpy.py b/website/fetch_pypi_downloads_via_clickpy.py index 6934dc0133..c7c979f2cf 100644 --- a/website/fetch_pypi_downloads_via_clickpy.py +++ b/website/fetch_pypi_downloads_via_clickpy.py @@ -16,9 +16,10 @@ looked up by README display name; when the display name differs from the canonical PyPI package (a squatter or a dead predecessor would be measured otherwise), add the mapping to the curated -data/pypi_name_overrides.json — normalized README name to the real -package, or null for projects that are not pip-installable so their -row is never queried. The file starts with a header row (name, package, +data/pypi_name_overrides.json — normalized README name to +{"package": ..., "reason": ...}, where package is the real PyPI name +or null for projects that are not pip-installable so their row is +never queried, and reason records why. The file starts with a header row (name, package, downloads, fetched_at) — package is the PyPI package the row actually measured ("-" for null overrides) — and every row carries the sweep date: a cache fetched within the last 7 days is current enough for @@ -53,7 +54,13 @@ def normalize(name: str) -> str: def load_overrides() -> dict[str, str | None]: - return json.loads(OVERRIDES_FILE.read_text()) + """Load curated overrides: normalized README name -> PyPI package to measure (None = never query). + + Each file entry is {"package": str | null, "reason": str | null}; the reason is + documentation only — required for null packages, optional for remaps. + """ + raw = json.loads(OVERRIDES_FILE.read_text()) + return {name: entry["package"] for name, entry in raw.items()} def resolve(name: str) -> str | None: From d3fec1f7fade7bc05e60f38b9a5fcda98d67c9df Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 19:15:21 +0800 Subject: [PATCH 165/168] feat: default-sort the website table by downloads per month Entries with a download count now sort first (descending), with stars, then Built-in, then name as fallback tiers for entries that lack a count. main.js mirrors this in its default activeSort, clean URL check, and third-click reset target. Sorting by stars remains one header click away. Co-Authored-By: Claude --- website/build.py | 14 +++++++++----- website/static/main.js | 6 +++--- website/tests/test_build.py | 2 ++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/website/build.py b/website/build.py index cba524faaf..6ca467abef 100644 --- a/website/build.py +++ b/website/build.py @@ -115,20 +115,24 @@ def load_downloads(path: Path) -> dict[str, int]: def sort_entries(entries: Sequence[TemplateEntry]) -> list[TemplateEntry]: - """Sort entries by stars descending, then name ascending. + """Sort entries by downloads descending, then name ascending. - Three tiers: starred entries first, stdlib second, other non-starred last. + Four tiers: entries with download counts first, then starred entries by + stars descending, then stdlib, then the rest. """ def sort_key(entry: TemplateEntry) -> tuple[int, int, int, str]: + downloads = entry["downloads"] stars = entry["stars"] name = entry["name"].lower() + if downloads is not None: + return (0, -downloads, 0, name) if stars is not None: builtin = 1 if entry.get("source_type") == "Built-in" else 0 - return (0, -stars, builtin, name) + return (1, -stars, builtin, name) if entry.get("source_type") == "Built-in": - return (1, 0, 0, name) - return (2, 0, 0, name) + return (2, 0, 0, name) + return (3, 0, 0, name) return sorted(entries, key=sort_key) diff --git a/website/static/main.js b/website/static/main.js index 073bb6c4b0..11d438613e 100644 --- a/website/static/main.js +++ b/website/static/main.js @@ -5,7 +5,7 @@ function getScrollBehavior() { } let activeFilter = null; -let activeSort = { col: "stars", order: "desc" }; +let activeSort = { col: "downloads", order: "desc" }; const searchInput = document.querySelector(".search"); const filterBar = document.querySelector(".filter-bar"); const filterValue = document.querySelector(".filter-value"); @@ -211,7 +211,7 @@ function buildQueryString() { const params = new URLSearchParams(); const query = searchInput ? searchInput.value.trim() : ""; if (query) params.set("q", query); - if (activeSort.col !== "stars" || activeSort.order !== "desc") { + if (activeSort.col !== "downloads" || activeSort.order !== "desc") { params.set("sort", activeSort.col); params.set("order", activeSort.order); } @@ -392,7 +392,7 @@ sortHeaders.forEach(function (th) { if (activeSort.col === col) { if (activeSort.order === defaultOrder) activeSort = { col: col, order: altOrder }; - else activeSort = { col: "stars", order: "desc" }; + else activeSort = { col: "downloads", order: "desc" }; } else { activeSort = { col: col, order: defaultOrder }; } diff --git a/website/tests/test_build.py b/website/tests/test_build.py index 3b417b2409..50627e27f7 100644 --- a/website/tests/test_build.py +++ b/website/tests/test_build.py @@ -463,6 +463,8 @@ def test_build_with_downloads_renders_column(self, tmp_path): assert "1,234,567" in html # Built-in entries never show PyPI counts: the asyncio row is the backport package assert "26,305,454" not in html + # Default sort: entries with download counts come first + assert html.index("My-Lib") < html.index("no-pypi") def test_build_fails_when_group_and_category_slug_collide(self, tmp_path): readme = textwrap.dedent("""\ From da491ff8ccacb383a0e68b6b7ddc105fcdfd7be2 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 19:16:03 +0800 Subject: [PATCH 166/168] docs: rename Downloads/Month column header to PyPI Downloads The header no longer carries the per-month unit; expand-row text keeps its 'downloads/month' wording. Co-Authored-By: Claude --- website/templates/category.html | 2 +- website/templates/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/website/templates/category.html b/website/templates/category.html index 51542767e2..ab95552b10 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -121,7 +121,7 @@

Results

- + diff --git a/website/templates/index.html b/website/templates/index.html index dc20049fca..efb69834d8 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -172,7 +172,7 @@

Results

- + From f5f7a1c50c3c88777a1f5d91d9426f210cc26091 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 16 Aug 2026 19:19:42 +0800 Subject: [PATCH 167/168] refactor: swap PyPI Downloads and GitHub Stars column order Downloads is now the default sort, so it sits directly after the project name in both the index and category table templates. The source-type badge stays in the stars cell. Co-Authored-By: Claude --- website/templates/category.html | 14 +++++++------- website/templates/index.html | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/website/templates/category.html b/website/templates/category.html index ab95552b10..4077db6115 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -117,12 +117,12 @@

Results

- - - + + + @@ -153,16 +153,16 @@

Results

else %}{{ category.name }}{% endif %} + + {% if entry.downloads is not none %}{{ + "{:,}".format(entry.downloads) }}{% else %}—{% endif %} + {% if entry.stars is not none %}{{ "{:,}".format(entry.stars) }}{% elif entry.source_type %}{{ entry.source_type }}{% else %}—{% endif %} - - {% if entry.downloads is not none %}{{ - "{:,}".format(entry.downloads) }}{% else %}—{% endif %} - Results - - - + + + @@ -204,16 +204,16 @@

Results

else %}{{ entry.categories[0] }}{% endif %} + + {% if entry.downloads is not none %}{{ + "{:,}".format(entry.downloads) }}{% else %}—{% endif %} + {% if entry.stars is not none %}{{ "{:,}".format(entry.stars) }}{% elif entry.source_type %}{{ entry.source_type }}{% else %}—{% endif %} - - {% if entry.downloads is not none %}{{ - "{:,}".format(entry.downloads) }}{% else %}—{% endif %} - Date: Sun, 16 Aug 2026 19:20:55 +0800 Subject: [PATCH 168/168] feat: show "Not on PyPI" badge for missing download counts Replaces the em dash in the PyPI Downloads column with a source-badge pill labeled "Not on PyPI", reusing the existing badge style used by the stars column for visual consistency. Sorting is unaffected since non-numeric cells already parse as missing. Co-Authored-By: Claude --- website/templates/category.html | 5 ++++- website/templates/index.html | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/website/templates/category.html b/website/templates/category.html index 4077db6115..e29e2f1780 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -155,7 +155,10 @@

Results

{% if entry.downloads is not none %}{{ - "{:,}".format(entry.downloads) }}{% else %}—{% endif %} + "{:,}".format(entry.downloads) }}{% else %}Not on PyPI{% endif %} {% if entry.stars is not none %}{{ "{:,}".format(entry.stars) }}{% diff --git a/website/templates/index.html b/website/templates/index.html index ac243c9bea..0bac14469a 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -206,7 +206,10 @@

Results

{% if entry.downloads is not none %}{{ - "{:,}".format(entry.downloads) }}{% else %}—{% endif %} + "{:,}".format(entry.downloads) }}{% else %}Not on PyPI{% endif %} {% if entry.stars is not none %}{{ "{:,}".format(entry.stars) }}{%