diff --git a/.claude/skills/audit-the-list/SKILL.md b/.claude/skills/audit-the-list/SKILL.md index 66118c1f..254c57e0 100644 --- a/.claude/skills/audit-the-list/SKILL.md +++ b/.claude/skills/audit-the-list/SKILL.md @@ -27,7 +27,7 @@ Done when every entry in scope has downloads (or a stated no-signal reason), rep ## 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. +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. A proposed addition under `docs/audit-logs.md` "Rejected Additions" seeds as reject from that line. ## 4. Review and go diff --git a/.claude/skills/preview-verdicts/SKILL.md b/.claude/skills/preview-verdicts/SKILL.md index 1c3bf843..ce363d06 100644 --- a/.claude/skills/preview-verdicts/SKILL.md +++ b/.claude/skills/preview-verdicts/SKILL.md @@ -1,24 +1,29 @@ --- name: preview-verdicts -description: Generate the interactive keep/drop/add 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. +description: Generate the interactive keep/remove/add/reject 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, Keep/Drop buttons (Add/Drop on proposed new entries) 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. +Maintainer review happens through an interactive HTML page: one row per entry with your seeded verdict and reason, verdict buttons 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]`. +1. Build the `DATA` array. A group is `[section, subcategory, rows]`; a row is `[entry, url, downloads, verdict, reason]`, plus an optional sixth `source` field. + - `source` says where a row came from when that is not obvious, such as the starred repo behind a scan candidate or an incumbent pulled in during the audit. The page shows a Source column only when a row has one. - `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`, `drop`, or `add`, seeded from the current adjudication or dry-run. `add` marks a proposed new entry; its row gets Add/Drop buttons, where Drop means not added. Show a replacement as two rows: the old entry `drop`, the new entry `add`. - - `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. + - `verdict` is seeded from the current adjudication or dry-run, and its row kind sets the buttons, so each verdict word names one outcome: + - Listed entry: `keep` or `remove` (taken out of README.md). + - Proposed new entry: `add` or `reject` (not added, logged under "Rejected Additions"). + - Structure question: `restructure` (take the change the reason or group note describes), `park` (no record, so it resurfaces), or `reject` (logged under "Rejected Additions"); seed it `restructure` or `park`. + - Show a replacement as two rows: the old entry `remove`, the new entry `add`. + - `reason` is plain language the maintainer reads cold — no invented shorthand. When fresh evidence contradicts the seeded verdict (a big download count on a remove or reject, 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 `local/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 -Each JSON row is `{section, subcategory, entry, my_verdict, your_verdict, reason}`. On a row seeded `add`, `your_verdict: "drop"` means do not add it. The maintainer's verdict is final — apply it, never re-argue it. An empty reason means the verdict stands unexplained; that is enough. +Each JSON row is `{section, subcategory, entry, my_verdict, your_verdict, reason}`, with verdict words as defined above. 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/preview-verdicts/template.html b/.claude/skills/preview-verdicts/template.html index 980fbc7e..1eb3e405 100644 --- a/.claude/skills/preview-verdicts/template.html +++ b/.claude/skills/preview-verdicts/template.html @@ -27,20 +27,24 @@ td.name { white-space: nowrap; font-weight: 600; } td.name a { color: var(--ink); text-decoration: none; border-bottom: 1px solid #c8c4c0; } td.name a:hover { border-bottom-color: var(--ink); } + td.source { font-size: .95rem; color: var(--muted); max-width: 14rem; } td.dl { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--muted); text-align: right; } td.mine { white-space: nowrap; } .badge { display: inline-block; font-size: .78rem; font-weight: 700; letter-spacing: .03em; padding: .12em .5em; border-radius: 4px; } .badge.keep { color: var(--keep); background: var(--keep-bg); } - .badge.drop { color: var(--drop); background: var(--drop-bg); } - .badge.add { color: var(--add); background: var(--add-bg); } + .badge.remove, .badge.reject { color: var(--drop); background: var(--drop-bg); } + .badge.add, .badge.restructure { color: var(--add); background: var(--add-bg); } + .badge.park { color: var(--muted); background: var(--line); } td.reason { color: #44403c; font-size: .95rem; max-width: 34rem; } td.yours { white-space: nowrap; } .seg { display: inline-flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; } .seg button { border: 0; background: #fff; padding: .3rem .8rem; font: inherit; font-size: .88rem; cursor: pointer; color: var(--muted); } .seg button + button { border-left: 1px solid var(--line); } - .seg button.on.k { background: var(--keep); color: #fff; font-weight: 700; } - .seg button.on.a { background: var(--add); color: #fff; font-weight: 700; } - .seg button.on.d { background: var(--drop); color: #fff; font-weight: 700; } + .seg button.on { color: #fff; font-weight: 700; } + .seg button.on.keep { background: var(--keep); } + .seg button.on.add, .seg button.on.restructure { background: var(--add); } + .seg button.on.remove, .seg button.on.reject { background: var(--drop); } + .seg button.on.park { background: var(--muted); } td.fb input { width: 100%; min-width: 14rem; font: inherit; font-size: .92rem; padding: .3rem .5rem; border: 1px solid var(--line); border-radius: 6px; background: #fff; } td.fb input:focus { outline: 2px solid var(--keep); outline-offset: 0; } .bar { position: fixed; bottom: 0; left: 0; right: 0; background: var(--ink); color: #fafaf9; display: flex; align-items: center; gap: 1.4rem; padding: .7rem 2.5rem; font-size: .95rem; } @@ -70,31 +74,34 @@ const KEY = "__KEY__"; let state = {}; try { state = JSON.parse(localStorage.getItem(KEY) || "{}"); } catch (e) {} +// A row's seeded verdict picks its button set, so each verdict word names one outcome. +const CHOICES = { keep: ["keep", "remove"], remove: ["keep", "remove"], add: ["add", "reject"], reject: ["add", "reject"], restructure: ["restructure", "park", "reject"], park: ["restructure", "park", "reject"] }; +const cap = v => v[0].toUpperCase() + v.slice(1); + function rowId(section, name) { return section + "::" + name; } function render() { const app = document.getElementById("app"); let html = "", lastSection = ""; + const hasSource = DATA.some(g => g[2].some(r => r.length > 5)); for (const [section, subcat, rows] of DATA) { if (section !== lastSection) { html += `

${section}

`; lastSection = section; } const parts = subcat.split(" — "); html += `

${parts[0]}${parts[1] ? ` — ${parts[1]}` : ""}

`; - html += ``; - for (const [name, url, dl, mine, reason] of rows) { + html += `
EntryDownloads/moMy verdictMy reasonYoursYour reason (optional)
${hasSource ? "" : ""}`; + for (const [name, url, dl, mine, reason, source] of rows) { const id = rowId(section, name); const s = state[id] || {}; const yours = s.verdict || mine; const changed = yours !== mine || (s.feedback || "").trim() !== ""; html += ` + ${hasSource ? `` : ""} `; @@ -137,14 +144,16 @@ function collect() { } function updateCounts() { - let keeps = 0, adds = 0, drops = 0, changed = 0; + const tally = {}; + let changed = 0; for (const [section, , rows] of DATA) for (const [name, , , mine] of rows) { const s = state[rowId(section, name)] || {}; const yours = s.verdict || mine; - if (yours === "keep") keeps++; else if (yours === "add") adds++; else drops++; + tally[yours] = (tally[yours] || 0) + 1; if (yours !== mine) changed++; } - document.getElementById("counts").innerHTML = `${keeps} keep · ${drops} drop · ${adds} add  |  ${changed} verdicts flipped`; + const counts = Object.entries(tally).map(([v, n]) => `${n} ${v}`).join(" · "); + document.getElementById("counts").innerHTML = `${counts}  |  ${changed} verdicts flipped`; } function copyFeedback() { diff --git a/.claude/skills/review-prs/SKILL.md b/.claude/skills/review-prs/SKILL.md index f5c3c890..70bb8ba3 100644 --- a/.claude/skills/review-prs/SKILL.md +++ b/.claude/skills/review-prs/SKILL.md @@ -16,7 +16,7 @@ Sort the batch: entry additions continue; anything else (typo fixes, website cha ## 2. Screen -Apply the Automatic Rejection rules that the diff and PR metadata answer without judgment. The recently-closed-duplicate rule needs a lookup: `gh pr list --repo vinta/awesome-python --state closed --search "" --limit 10`. A screened-out PR goes straight to step 4 as a close, with the rule it broke as its reason. +Apply the Automatic Rejection rules that the diff and PR metadata answer without judgment. The recently-closed-duplicate rule needs a lookup: `gh pr list --repo vinta/awesome-python --state closed --search "" --limit 10`; a project under `docs/audit-logs.md` "Rejected Additions" also counts as previously rejected unless the PR brings evidence newer than its line. A screened-out PR goes straight to step 4 as a close, with the rule it broke as its reason. Resolve each survivor's target use case against the current README — a diff's context lines show the base the PR was written on, which may have changed since. A merge conflict rides to the Merge arm, which absorbs it. Done when every surviving PR names its target use case. diff --git a/.claude/skills/scan-github-stars/SKILL.md b/.claude/skills/scan-github-stars/SKILL.md new file mode 100644 index 00000000..3b019986 --- /dev/null +++ b/.claude/skills/scan-github-stars/SKILL.md @@ -0,0 +1,36 @@ +--- +name: scan-github-stars +description: Scan the maintainer's GitHub stars for README.md addition candidates; incremental by default, `full` rejudges stars judged before. +argument-hint: [full] +disable-model-invocation: true +--- + +# Scan GitHub stars + +A star scan turns the maintainer's GitHub stars into proposed additions. Every star the scan sees ends in one place: listed in README.md, screened out in `local/starred-scan.tsv`, or rejected under `docs/audit-logs.md` "Rejected Additions". Judgment belongs to `audit-the-list` and the rules to CONTRIBUTING.md; this skill only sources candidates and records outcomes. + +## 1. Scan + +Run `uv run python .claude/skills/scan-github-stars/scripts/scan_github_stars.py`, adding `--full` when the argument is `full`. With no ledger yet, a plain run already covers every star. Print the drop counts from stderr. Done when the candidate TSV is in hand. + +## 2. Screen + +Judge each candidate from its name, description, topics, and language against CONTRIBUTING Quality Requirement 1 (Serves Python Developers), and name the current use case it would compete in. The screen is loose: drop only what plainly fails, and pass anything uncertain on, since `audit-the-list` is the real judge. In a full scan, read the `prior` column as context and overturn a rejection only on new evidence. + +Append each screen-out to `local/starred-scan.tsv` as it is decided, one `repoyyyy-mm-ddreason` row (create the file with header `repo date reason`), so an interrupted run keeps its work. The file is append-only; the script reads the last row per repo. A survivor no current use case fits is a structure question: carry it to review with its evidence. Done when every candidate is a ledger row, holds a target use case, or is a structure question. + +## 3. Judge + +Group survivors by target use case. Per group, invoke `audit-the-list` with: "Judge proposed entries for the
use case. Evidence and Verdicts steps only; report the verdicts back. No preview page, no README changes, no commits." A reject whose reason names an unlisted project as the better pick turns that project into a candidate too: judge it in the same group and mark its source as found in the audit, not starred. Done when every survivor holds an add or reject verdict with a reason, and each add at cap names the entry it displaces. + +## 4. Review + +Run `preview-verdicts` over all groups: survivors as `add` or `reject` rows, displaced entries as `remove`, structure questions as `park` or `restructure` rows, and any `prior` verdict quoted in the row's reason. Seed `park` on any row whose verdict rests on a judgment call, except an add where only the tier is in doubt, so the page holds only settled calls. Done when the maintainer's feedback is processed and they gave the go. + +## 5. Record + +- **Added**: follow `audit-the-list` step 5 for the README change, one commit per entry. When the entry links a different repo than the star (a Python binding or client of a starred engine), also append a ledger row `already listed as ()` for the star, since the script only recognizes a star whose own repo is linked. +- **Rejected**: a candidate that reached review and was not added gets one line under "Rejected Additions": `- owner/repo -- yyyy-mm-dd, /month (): .`, replacing its earlier line. +- **Parked**: a row the maintainer parks gets no record, so it resurfaces next run. + +Done when every candidate from step 1 is listed in README.md, a ledger row, a Rejected Additions line, or parked by the maintainer. diff --git a/.claude/skills/scan-github-stars/scripts/scan_github_stars.py b/.claude/skills/scan-github-stars/scripts/scan_github_stars.py new file mode 100644 index 00000000..c0b5fc4e --- /dev/null +++ b/.claude/skills/scan-github-stars/scripts/scan_github_stars.py @@ -0,0 +1,118 @@ +"""List the maintainer's GitHub stars that could be README.md candidates. + +Drops stars that fail a check needing no judgment: already listed, own repo, +archived, no push in 12 months, or created under a month ago. These drops are +recomputed every run, so a repo that becomes active again resurfaces. An +incremental run also drops stars already judged: model screen-outs in +local/starred-scan.tsv and maintainer rejections under docs/audit-logs.md +"Rejected Additions". `--full` keeps them and shows the earlier verdict in the +`prior` column. Prints survivors as TSV on stdout, drop counts on stderr. +""" + +import argparse +import json +import re +import subprocess +import sys +from collections import Counter +from datetime import UTC, datetime, timedelta +from pathlib import Path +from typing import TypedDict + +ROOT = Path(__file__).resolve().parents[4] +sys.path.insert(0, str(ROOT / "website")) + +from readme_parser import parse_readme + +LEDGER = ROOT / "local" / "starred-scan.tsv" +REGISTER = ROOT / "docs" / "audit-logs.md" +GITHUB_REPO_RE = re.compile(r"^https://github\.com/([^/#?]+/[^/#?]+)") +REJECTED_LINE_RE = re.compile(r"^- (\S+) -- (.+)$") + + +class Owner(TypedDict): + login: str + + +class Star(TypedDict): + full_name: str + owner: Owner + archived: bool + pushed_at: str + created_at: str + language: str | None + stargazers_count: int + topics: list[str] + description: str | None + + +def gh(*args: str) -> str: + return subprocess.run(["gh", *args], capture_output=True, text=True, check=True).stdout + + +def listed_repos() -> set[str]: + repos = set() + for group in parse_readme((ROOT / "README.md").read_text()): + for category in group["categories"]: + for link in [*category["entries"], *(sub for entry in category["entries"] for sub in entry["also_see"])]: + if match := GITHUB_REPO_RE.match(link["url"]): + repos.add(match.group(1).removesuffix(".git").lower()) + return repos + + +def prior_verdicts() -> dict[str, str]: + """Repo -> earlier verdict. The ledger is append-only, so its last row per repo wins; a maintainer rejection outranks both.""" + prior = {} + if LEDGER.exists(): + for line in LEDGER.read_text().splitlines()[1:]: + repo, date, reason = line.split("\t", 2) + prior[repo.lower()] = f"screened out {date}: {reason}" + register = REGISTER.read_text().splitlines() + start = register.index("## Rejected Additions") + for line in register[start + 1 :]: + if line.startswith("## "): + break + if match := REJECTED_LINE_RE.match(line): + prior[match.group(1).lower()] = f"rejected {match.group(2)}" + return prior + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument("--full", action="store_true", help="rejudge stars already screened out or rejected") + args = parser.parse_args() + + now = datetime.now(UTC) + login = gh("api", "user", "--jq", ".login").strip().lower() + listed = listed_repos() + prior = prior_verdicts() + + stars: list[Star] = [json.loads(line) for line in gh("api", "--paginate", "user/starred?per_page=100", "--jq", ".[]").splitlines()] + dropped = Counter() + print("repo\tlanguage\tstars\tpushed\ttopics\tdescription\tprior") + for star in stars: + repo = star["full_name"].lower() + verdict = prior.get(repo) or prior.get(f"{star['owner']['login'].lower()}/*") + if repo in listed: + dropped["already listed"] += 1 + elif star["owner"]["login"].lower() == login: + dropped["own repo"] += 1 + elif star["archived"]: + dropped["archived"] += 1 + elif datetime.fromisoformat(star["pushed_at"]) < now - timedelta(days=365): + dropped["no push in 12 months"] += 1 + elif datetime.fromisoformat(star["created_at"]) > now - timedelta(days=30): + dropped["created under a month ago"] += 1 + elif verdict and not args.full: + dropped["judged before"] += 1 + else: + description = " ".join((star["description"] or "").split()) + print("\t".join([star["full_name"], star["language"] or "-", str(star["stargazers_count"]), star["pushed_at"][:10], ",".join(star["topics"]), description, verdict or ""])) + + print(f"{len(stars)} stars; {len(stars) - dropped.total()} candidates", file=sys.stderr) + for reason, count in dropped.most_common(): + print(f" dropped {count}: {reason}", file=sys.stderr) + + +if __name__ == "__main__": + main() diff --git a/README.md b/README.md index 73a63a73..e2ae0b7a 100644 --- a/README.md +++ b/README.md @@ -168,10 +168,13 @@ _Libraries for building AI applications, LLM integrations, and autonomous agents - Pre-trained Models - [transformers](https://github.com/huggingface/transformers) - The model-definition framework for pretrained models in text, computer vision, audio, video, and multimodal tasks, for inference and training. - [sentence-transformers](https://github.com/huggingface/sentence-transformers) - Compute embeddings, run retrieval, and rerank results with pretrained and fine-tuned models. -- LLM Inference and Serving +- Local LLM Inference + - [ollama](https://github.com/ollama/ollama-python) - Python client for Ollama, which downloads and runs open-weight LLMs locally. + - [llama-cpp-python](https://github.com/abetlen/llama-cpp-python) - Python bindings for llama.cpp, for running GGUF models locally. + - [mlx-lm](https://github.com/ml-explore/mlx-lm) - Run and fine-tune large language models on Apple Silicon with MLX. +- LLM Serving - [vllm](https://github.com/vllm-project/vllm) - A high-throughput and memory-efficient inference and serving engine for LLMs. - [sglang](https://github.com/sgl-project/sglang) - A high-performance serving framework for large language models and multimodal models. - - [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 @@ -207,6 +210,7 @@ _Libraries for Machine Learning. Also see [awesome-machine-learning](https://git - General - [scikit-learn](https://github.com/scikit-learn/scikit-learn) - The most popular Python library for Machine Learning with extensive documentation and community support. + - [imbalanced-learn](https://github.com/scikit-learn-contrib/imbalanced-learn) - Resampling techniques for datasets with imbalanced classes, compatible with scikit-learn. - [pgmpy](https://github.com/pgmpy/pgmpy) - A Python library for causal and probabilistic reasoning with graphical models. - [feature-engine](https://github.com/feature-engine/feature_engine) - sklearn compatible API with the widest toolset for feature engineering and selection. - Gradient Boosting @@ -218,6 +222,9 @@ _Libraries for Machine Learning. Also see [awesome-machine-learning](https://git - [statsforecast](https://github.com/Nixtla/statsforecast) - Fast statistical forecasting models such as ARIMA, ETS, and Theta, compiled with numba. - [sktime](https://github.com/sktime/sktime) - A unified scikit-learn-style framework for forecasting and other time-series learning tasks. - [timesfm](https://github.com/google-research/timesfm) - A pretrained foundation model from Google Research for time-series forecasting, with non-commercial default weights. +- Hyperparameter Optimization + - [optuna](https://github.com/optuna/optuna) - A hyperparameter optimization framework with define-by-run search spaces and pruning of unpromising trials. + - [hyperopt](https://github.com/hyperopt/hyperopt) - Distributed asynchronous hyperparameter optimization with Tree-structured Parzen Estimators. ### Natural Language Processing @@ -231,6 +238,7 @@ _Libraries for working with human 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 (拼音). + - [OpenCC](https://github.com/BYVoid/OpenCC) - Conversion between Traditional and Simplified Chinese, with regional variants and phrase-level rules. - [pangu.py](https://github.com/vinta/pangu.py) - Paranoid text spacing. ### Computer Vision @@ -399,7 +407,7 @@ _Libraries to automate web scraping and extract web content._ - [scrapy](https://github.com/scrapy/scrapy) - A fast high-level web crawling and scraping framework. - [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. - [stagehand](https://github.com/browserbase/stagehand) - A fast and token-efficient browser automation SDK to extract data and perform self-healing actions on web pages. - - [jev-ultrafast](https://github.com/browser-use/jev-ultrafast) - A fast browser agent that picks actions from an indexed table of page elements through TypeSafe's hosted Jev API, using a small LLM only to type text. + - [scrapling](https://github.com/D4Vinci/Scrapling) - An adaptive scraping framework whose selectors relocate elements after page changes, with stealth fetchers and spiders. - Content Extraction - [markdownify](https://github.com/matthewwithanm/python-markdownify) - Convert HTML to Markdown, with customizable tag handling. - [feedparser](https://github.com/kurtmckee/feedparser) - Universal feed parser. @@ -441,8 +449,10 @@ _Libraries for connecting and operating databases._ - PostgreSQL - [awesome-postgres](https://github.com/dhamaniasad/awesome-postgres) - [psycopg](https://github.com/psycopg/psycopg) - A PostgreSQL adapter for Python, the successor to psycopg2. - [asyncpg](https://github.com/MagicStack/asyncpg) - A fast PostgreSQL Database Client Library for Python/asyncio. + - [pgvector](https://github.com/pgvector/pgvector-python) - pgvector support for Python, adding vector types and similarity search to psycopg, asyncpg, SQLAlchemy, and Django. - SQLite - [awesome-sqlite](https://github.com/planetopendata/awesome-sqlite) - [sqlite3](https://docs.python.org/3/library/sqlite3.html) - (Python standard library) SQLite interface compliant with DB-API 2.0. + - [apsw](https://github.com/rogerbinns/apsw) - Another Python SQLite Wrapper, exposing the complete SQLite C API. - [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. @@ -464,6 +474,7 @@ _In-process databases usable directly from Python._ - [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 + - [faiss-cpu](https://github.com/facebookresearch/faiss) - A library for efficient similarity search and clustering of dense vectors. - [lancedb](https://github.com/lancedb/lancedb) - A developer-friendly embedded retrieval database for multimodal AI. - [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) - A lightweight, in-process vector database that embeds directly into applications. @@ -476,9 +487,9 @@ _Libraries for caching data._ - [cachetools](https://github.com/tkem/cachetools) - Extensible memoizing collections and decorators. - [diskcache](https://github.com/grantjenks/python-diskcache) - SQLite and file backed cache backend, compatible with Django. +- [django-redis](https://github.com/jazzband/django-redis) - Full-featured Redis cache backend for Django. - [hishel](https://github.com/karpetrosyan/hishel) - RFC 9111 compliant HTTP caching for clients like httpx and requests and servers like FastAPI, with sync and async support. - [django-cacheops](https://github.com/Suor/django-cacheops) - A slick ORM cache with automatic granular event-driven invalidation. -- [dogpile.cache](https://github.com/sqlalchemy/dogpile.cache) - dogpile.cache is a next generation replacement for Beaker made by the same authors. ### Search @@ -493,10 +504,14 @@ _Libraries and software for indexing and performing search queries on data._ _Libraries for serializing complex data types._ -- [msgpack](https://github.com/msgpack/msgpack-python) - MessagePack serializer implementation for Python. -- [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 Formats + - [msgpack](https://github.com/msgpack/msgpack-python) - MessagePack serializer implementation for Python. + - [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. +- Object Pickling + - [cloudpickle](https://github.com/cloudpipe/cloudpickle) - Extends pickle to functions, lambdas, and interactively defined classes, for shipping code to remote workers. + - [dill](https://github.com/uqfoundation/dill) - Extends pickle to serialize almost any Python object, including closures and whole interpreter sessions. **Data & Science** @@ -542,7 +557,7 @@ _Libraries for visualizing data. Also see [awesome-javascript](https://github.co - [bokeh](https://github.com/bokeh/bokeh) - Interactive Web Plotting for Python. - Specialized - [graphviz](https://github.com/xflr6/graphviz) - Simple Python interface for creating and rendering Graphviz graphs. - - [cartopy](https://github.com/SciTools/cartopy) - A cartographic python library with matplotlib support. + - [cartopy](https://github.com/SciTools/cartopy) - A cartographic Python library with matplotlib support. - [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. @@ -642,7 +657,8 @@ _Tools of static analysis, linters and code quality checkers. Also see [awesome- - [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. + - [rope](https://github.com/python-rope/rope) - Rope is a Python refactoring library. + - [ast-grep-cli](https://github.com/ast-grep/ast-grep) - A CLI tool for structural code search, linting, and rewriting based on syntax trees. - Type Checkers - [awesome-python-typing](https://github.com/typeddjango/awesome-python-typing) - [mypy](https://github.com/python/mypy) - A static type checker for Python. - [ty](https://github.com/astral-sh/ty) - An extremely fast Python type checker and language server. @@ -700,6 +716,7 @@ _Libraries for debugging code._ - [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. + - [django-silk](https://github.com/jazzband/django-silk) - Live profiling and inspection of HTTP requests and database queries for Django. - [icecream](https://github.com/gruns/icecream) - Inspect variables, expressions, and program execution with a single, simple function call. - [flask-debugtoolbar](https://github.com/pallets-eco/flask-debugtoolbar) - A port of the django-debug-toolbar to flask. @@ -868,7 +885,7 @@ _Libraries for working with graphical user interface applications._ - [PyQt6](https://www.riverbankcomputing.com/static/Docs/PyQt6/) - Python bindings for the [Qt](https://www.qt.io/) cross-platform application and UI framework. - 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. + - [customtkinter](https://github.com/tomschimansky/customtkinter) - A modern and customizable Python UI-library based on Tkinter. - Web-based - [pywebview](https://github.com/r0x0r/pywebview) - A lightweight cross-platform native wrapper around a webview component. - [nicegui](https://github.com/zauberzeug/nicegui) - An easy-to-use, Python-based UI framework, which shows up in your web browser. @@ -922,6 +939,7 @@ _Libraries for parsing and manipulating specific file formats._ - [tablib](https://github.com/jazzband/tablib) - A module for Tabular Datasets in XLS, CSV, JSON, YAML. - File Conversion - [markitdown](https://github.com/microsoft/markitdown) - Python tool for converting files and office documents to Markdown. + - [pypandoc](https://github.com/JessicaTegner/pypandoc) - A thin wrapper for pandoc, the universal document converter. - [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. @@ -949,11 +967,14 @@ _Libraries for parsing and manipulating specific file formats._ _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. -- [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. +- Paths and File Watching + - [pathlib](https://docs.python.org/3/library/pathlib.html) - (Python standard library) A cross-platform, object-oriented path library. + - [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. +- File Type Detection + - [mimetypes](https://docs.python.org/3/library/mimetypes.html) - (Python standard library) Map filenames to MIME types. + - [python-magic](https://github.com/ahupp/python-magic) - A Python interface to the libmagic file type identification library. + - [magika](https://github.com/google/magika) - Detects file content types with a deep-learning model. **Media** @@ -1069,6 +1090,7 @@ _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. +- [mise](https://github.com/jdx/mise) - A polyglot tool version manager that installs Python versions and reads .python-version files. ### Package Management @@ -1106,7 +1128,7 @@ _Libraries to create packaged executables for release distribution._ - [pex](https://github.com/pex-tool/pex) - A tool for building self-contained Python executable environments (PEP 441 zipapps). - [cx-Freeze](https://github.com/marcelotduarte/cx_Freeze) - 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. + - [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 @@ -1141,10 +1163,13 @@ _Frameworks and tools for penetration testing._ ### Supply Chain Security -_Tools for auditing dependencies against known vulnerabilities._ +_Tools for auditing dependencies against known vulnerabilities and scanning for leaked secrets._ -- [pip-audit](https://github.com/pypa/pip-audit) - Audits Python environments and dependency trees for known vulnerabilities, using the Python Packaging Advisory Database or OSV. -- [uv-audit](https://github.com/astral-sh/uv) - (part of uv) uv's [dependency vulnerability scanning](https://docs.astral.sh/uv/reference/cli/#uv-audit) backed by OSV. +- Dependency Audits + - [pip-audit](https://github.com/pypa/pip-audit) - Audits Python environments and dependency trees for known vulnerabilities, using the Python Packaging Advisory Database or OSV. + - [uv-audit](https://github.com/astral-sh/uv) - (part of uv) uv's [dependency vulnerability scanning](https://docs.astral.sh/uv/reference/cli/#uv-audit) backed by OSV. +- Secret Scanning + - [betterleaks](https://github.com/betterleaks/betterleaks) - Finds leaked secrets in git history, directories, and files, from the original author of gitleaks. ### Web Security diff --git a/docs/audit-logs.md b/docs/audit-logs.md index ae95952e..14c6713e 100644 --- a/docs/audit-logs.md +++ b/docs/audit-logs.md @@ -39,7 +39,8 @@ Entries admitted as challengers without adoption-trajectory evidence, by maintai - seleniumbase -- admitted 2026-08-16 (PR #3284) as a Browser Automation challenger. It wraps selenium, the successor trajectory in the use case belongs to playwright, and its distinct value is its stealth/UC mode. Admitted because that stealth value counts toward Browser Automation. - semantica -- kept 2026-10-01 in the AI and Agents audit as a Data Layer challenger at 16,582 downloads/month on ClickPy, with no adoption-trajectory evidence found. Kept by maintainer decision. -- jev-ultrafast -- kept 2026-09-24 as a Web Scraping Frameworks challenger, recorded 2026-10-02. Admitted while the repo was under a month old and not on PyPI, so it has no download signal and no adoption-trajectory evidence; its README calls it an MVP and it needs a hosted TypeSafe API key. Kept by maintainer decision. +- hyperopt -- admitted 2026-10-16 as a Hyperparameter Optimization challenger at 1,793,872 downloads/month on ClickPy. Its 0.3.0 release came after a 4.5-year gap and it has no adoption-trajectory evidence. Admitted by maintainer decision. +- magika -- admitted 2026-10-16 as a File Type Detection challenger at 16,388,380 downloads/month on ClickPy. markitdown requires it, so most of that count is transitive, and no adoption-trajectory evidence was found. Admitted by maintainer decision. ### Cap Exceptions @@ -67,6 +68,99 @@ These entries sit past the 12-month activity requirement without an override. Ea - schedule -- kept 2026-08-16, recorded 2026-10-02. Last commit 2024-05-25. - sortedcontainers +## Rejected Additions + +Projects the maintainer decided not to list, with the evidence at decision time, keyed by GitHub `owner/repo` (`owner/*` for a whole organization). PR reviews and star scans check here before proposing a project again. Rejudge one only on new evidence. + +- BrianPugh/autoregistry -- 2026-08-23, 16,758 downloads/month: 77 stars. +- MarcBresson/schedium -- 2026-08-23, 381 downloads/month: repository created 2026-02-05. +- ets-labs/python-dependency-injector -- 2026-08-23, 9,086,069 downloads/month: the Dependency Injection use case was declined, since FastAPI's Depends and pytest fixtures absorb most of the need, leaving a leader with no challenger field. +- konradhalas/dacite -- 2026-08-23, 23,147,569 downloads/month: last push 2025-03-17, fails the activity rule. +- reagento/dishka -- 2026-08-23, 769,893 downloads/month: declined with the Dependency Injection use case. +- xberg-io/* -- 2026-08-16: coordinated multi-entry self-promotion; four planted entries were removed (xberg, liter-llm, tree-sitter-language-pack, html-to-markdown). Reject any project from this organization on sight. +- AbstractUmbra/audioop -- 2026-10-16, 7,714,737 downloads/month (ClickPy): gradio and discord.py require it on Python 3.13+, so the count is transitive. It is a backport of a removed stdlib module, not an audio tool readers choose. +- alteryx/featuretools -- 2026-10-16, 106,521 downloads/month (ClickPy): Fails Active: last commit 2024-11-13, last release 2024-05-14. +- AnswerDotAI/fastcore -- 2026-10-16, 24,139,424 downloads/month (ClickPy): ghapi requires it, and the jump from 11.5M to 50.9M is pull from that dependency. It is a fastai grab-bag, not a built-in class enhancement. +- anthropics/claude-code-security-review -- 2026-10-16, no PyPI download signal: A language-agnostic GitHub Action with no releases and no commits since 2026-02-11. Not Python work. +- apple-aiml-research/ml-stable-diffusion -- 2026-10-16, no PyPI download signal: Fails Active: the last human commit is 2025-07-03, and the 2026 commit is a bot. It is a Core ML/Swift path, not a Python generation library. +- arrobalytics/django-ledger -- 2026-10-16, 17,102 downloads/month (ClickPy): An accounting engine, not an ERP suite. Small demand, no Development Status classifier, and no production case studies found. +- asdf-vm/asdf -- 2026-10-16, no PyPI download signal: The tool users are leaving for mise, with the 0.16 Go rewrite cited as the trigger. PyPI "asdf" is an unrelated astronomy package. +- AUTOMATIC1111/stable-diffusion-webui -- 2026-10-16, no PyPI download signal: Fails Active: the last commit on the default branch is 2024-07-27, and its pushed_at date doesn't reflect code changes. +- binaryornot/binaryornot -- 2026-10-16, 13,794,027 downloads/month (ClickPy): cookiecutter requires it, which accounts for about half the count. It does a narrow job, and the use case is at cap. +- bisohns/search-engine-parser -- 2026-10-16, 22,138 downloads/month (ClickPy): Last release 2022-11, and it pins lxml<5. It scrapes search results pages, not page content. +- bookieio/breadability -- 2026-10-16, 106,712 downloads/month (ClickPy): sumy pulls in almost all of the count. Its first release since 2014 lists Python 3.6 classifiers. +- boson-ai/higgs-audio -- 2026-10-16, 416 downloads/month (ClickPy): Two releases, both on 2025-10-03, and the PyPI homepage is a placeholder. v3 moved to Hugging Face plus an API, so nothing pip-installable is maintained. +- caesar0301/treelib -- 2026-10-16, 1,532,895 downloads/month (ClickPy): anytree (6.0M) is the bigger tree library at 4x the downloads, so treelib is not the obvious choice. +- chibisov/drf-extensions -- 2026-10-16, 2,067,903 downloads/month (ClickPy): Last release declares Django<6.0, and it is a DRF add-on, not an API framework. +- cknd/stackprinter -- 2026-10-16, 334,597 downloads/month (ClickPy): Flat downloads, and one release after a two-year gap. No sign of a challenger trajectory. +- clips/pattern -- 2026-10-16, no PyPI download signal: The code ended in 2018, and the 2026 commit is a README edit. PyPI "pattern" is now an unrelated package. Previously removed 2026-03-21 (f52c85a) as unmaintained, and nothing has changed since. +- closeio/ciso8601 -- 2026-10-16, 6,373,074 downloads/month (ClickPy): The use case is full. Its own docs tell users on Python 3.11+ to use datetime.fromisoformat unless they need the speed, so it is a narrow speed-up, not a general datetime library. +- codelucas/newspaper -- 2026-10-16, 468,795 downloads/month (ClickPy): The 2026-03-21 removal (1d09426, unmaintained) still holds: last release was 2018-09, and the 2026 push came with no release. +- coleifer/unqlite-python -- 2026-10-16, 11,386 downloads/month (ClickPy): It binds an embedded database rather than being a server driver, and has negligible demand in either home. +- coleifer/walrus -- 2026-10-16, 182,584 downloads/month (ClickPy): A utility layer over redis-py, not a driver, at under 0.1% of redis's 204M downloads. +- crccheck/django-object-actions -- 2026-10-16, 2,366,676 downloads/month (ClickPy): An add-on for Django admin buttons, not an admin panel. The source of its download count is unknown. +- davidhalter/jedi -- 2026-10-16, 102,370,894 downloads/month (ClickPy): ipython requires it, and its count almost exactly matches ipython's 102.6M. Its job is editor and REPL autocompletion, which the list dropped along with the Editor Plugins section (c87fdac). +- DerwenAI/pytextrank -- 2026-10-16, 82,707 downloads/month (ClickPy): Fails Active: last commit 2024-05-21, last release 2024-02-21. +- django-haystack/celery-haystack -- 2026-10-16, 1,919 downloads/month (ClickPy): Last release 2015-12. +- django-parler/django-parler -- 2026-10-16, 160,493 downloads/month (ClickPy): django-modeltranslation (826,853) has 5x its downloads, so it is not the obvious choice for Django model translation. +- doableware/djongo -- 2026-10-16, 57,392 downloads/month (ClickPy): Its latest release (1.3.7, 2024-11) pins django<=3.1.12, so it can't be installed with any supported Django. django-mongodb-backend already does this job. +- Doist/bitmapist -- 2026-10-16, 7,385 downloads/month (ClickPy): A Redis bitmap analytics library, not a driver, with negligible demand. Its metadata caps Python below 3.14 and redis below 6.0. +- dpath-maintainers/dpath-python -- 2026-10-16, 8,884,938 downloads/month (ClickPy): checkov and airbyte-cdk pull it in, leaving about 3.5M independent, below the section's floor (python-box, 4.9M). Last release 2024-06. +- dpkp/kafka-python -- 2026-10-16, 17,148,353 downloads/month (ClickPy): It was removed as unmaintained on 2026-03-21 (e8d3d29), but it was still releasing then and has shipped 3.0.0 through 3.0.11 since (June to August 2026), so that reason no longer holds. It is held back by tier: confluent-kafka (41.5M) is the default for new projects, and kafka-python is the pure-Python fallback rather than a successor. +- dwolfhub/zxcvbn-python -- 2026-10-16, 4,673,093 downloads/month (ClickPy): Password-strength estimation is not cryptography, and there is no use case for passwords. It also fails Active: last commit on master was 2025-10-06. +- explorerhq/sql-explorer -- 2026-10-16, 213,897 downloads/month (ClickPy): A SQL reporting tool, not an admin panel, and below the smallest incumbent (django-grappelli, 281,247). +- frostming/marko -- 2026-10-16, 5,798,780 downloads/month (ClickPy): The obvious tier (markdown-it-py, markdown, mistune) is full. Its growth roughly tracks the general ClickPy inflation, and no source shows it replacing any of the three. +- ggml-org/whisper.cpp -- 2026-10-16, 734,136 downloads/month (ClickPy): Python uses it through the separate third-party absadiki/pywhispercpp (349 stars). It does faster-whisper's job (12.1M) with no sign of overtaking it. The download count is unexplained for 349 stars. +- gitleaks/gitleaks -- 2026-10-16, no PyPI download signal: Secret Scanning was minted with betterleaks alone. gitleaks is a language-agnostic Go binary with slowing activity (last release 2026-03-21). +- hhatto/autopep8 -- 2026-10-16, 7,132,827 downloads/month (ClickPy): The use case holds 6 entries under a cap exception, and none is weaker (flake8 39.6M, bandit 24.5M). Last release was 2025-01, and the 2026 commits are dependabot only. +- html5lib/html5lib-python -- 2026-10-16, 26,055,801 downloads/month (ClickPy): The 2026-03-21 removal (7f21136, no release since 2019) still holds: last release 1.1 in 2020-06. The count comes from 3,281 dependents rather than people picking it, and justhtml already covers pure-Python HTML5 parsing. +- huggingface/speech-to-speech -- 2026-10-16, 2,714 downloads/month (ClickPy): An end-to-end voice pipeline app, not an ASR/TTS library, and far below the smallest Speech entry (funasr, 297,003). +- jazzband/django-pipeline -- 2026-10-16, 222,640 downloads/month (ClickPy): The 2026-03-21 removal (6b59080) gave overlap with django-compressor as the reason, which still holds: django-compressor has 11x its downloads. +- jundot/omlx -- 2026-10-16, no PyPI download signal: A macOS menu-bar app (repo created 2026-02-13), not a library. mlx-lm already covers Apple Silicon. +- jupyter/docker-stacks -- 2026-10-16, no PyPI download signal: Container images that package notebook (already listed), not an interpreter. +- kaifcodec/user-scanner -- 2026-10-16, 16,772 downloads/month (ClickPy): The use case is at cap. sherlock-project does the same username OSINT job at 4x the downloads. Repo created 2025-10. +- keleshev/schema -- 2026-10-16, 19,658,077 downloads/month (ClickPy): Removed as unmaintained on 2026-03-21 (e8d3d29), and activity has not resumed: the last release was 0.7.8 in 2025-10, with only a push since. It is classified Alpha and is not a successor to pydantic or jsonschema. +- kellyjonbrazil/jc -- 2026-10-16, 626,452 downloads/month (ClickPy): Parser is at cap (floor: parsy, 3.96M). jc does a different job (CLI output to JSON) and has no entry to replace. +- lexiforest/curl_cffi -- 2026-10-16, 31,930,921 downloads/month (ClickPy): About 17.4M of this is pulled in by yfinance, leaving roughly 14M of its own demand. HTTP Clients General is at cap, and web sources frame it as a TLS-fingerprint impersonation tool for getting past anti-bot blocks, not as a successor to requests or httpx2. No use case covers impersonation. +- LPgenerator/django-db-mailer -- 2026-10-16, 1,143 downloads/month (ClickPy): Last release 2018-10. +- mahmoud/glom -- 2026-10-16, 23,112,427 downloads/month (ClickPy): semgrep requires it, leaving about 3.5M independent. It is a transformer for nested data rather than a built-in class enhancement. +- mailgun/flanker -- 2026-10-16, 36,887 downloads/month (ClickPy): The 2026-03-21 removal (7f21136, abandoned by Mailgun) still holds: last release 2019-12. It parses mail rather than sending it. +- matthewwithanm/django-imagekit -- 2026-10-16, 380,436 downloads/month (ClickPy): Django-specific and below General's floor. Django thumbnailing has no clear leader (sorl-thumbnail 485K, easy-thumbnails 469K). +- matthewwithanm/pilkit -- 2026-10-16, 380,588 downloads/month (ClickPy): Pulled in by django-imagekit (nearly identical counts). Last release 2023-09. +- maxfischer2781/asyncstdlib -- 2026-10-16, 4,288,321 downloads/month (ClickPy): Async I/O already holds 6 entries under a cap exception. This is a different job (async versions of builtins and itertools), and aiostream (3.8M) is an equal peer. +- MemPalace/mempalace -- 2026-10-16, 56,453 downloads/month (ClickPy): Data Layer is at cap. Agent memory is mem0's job (2.0M), so there is no one-in-one-out case. Its April 2026 launch coverage centred on disputed benchmarks (the 100% LongMemEval claim was pulled), it is classified Beta, and its popularity is driven by stars (59.6k stars vs 56k downloads). +- mewwts/addict -- 2026-10-16, 6,120,693 downloads/month (ClickPy): Fails Active: last commit 2021-01, last release 2020-11. python-box, already listed, does the same job. +- microsoft/bocpy -- 2026-10-16, 9,933 downloads/month (ClickPy): Created 2026-02, classified Beta, 201 stars. No adoption-trajectory evidence. +- mongodb/motor -- 2026-10-16, 9,226,799 downloads/month (ClickPy): Deprecated in favor of the PyMongo Async API (2025-05-14) and end-of-life since 2026-05-14. Its last release was 3.7.1 in 2025-05, and pymongo is listed. The earlier removal (d9bba73, 2026-01-16, "unmaintained") still holds. +- mpdavis/python-jose -- 2026-10-16, 32,386,854 downloads/month (ClickPy): The 2026-03-21 removal (f50bd8f, superseded) still holds: FastAPI's JWT tutorial now uses PyJWT, and several dependents migrated away after CVE-2024-33663. No release since 2025-05. +- myusuf3/delorean -- 2026-10-16, 107,732 downloads/month (ClickPy): Removed 2024-02-23 (8524f28). 2.0.0 (2026-08) is its first release since 2018, and that day's commits are docs and CI only. It is Beta, has little demand, and the use case is full. +- noripyt/django-cachalot -- 2026-10-16, 244,358 downloads/month (ClickPy): Does the same job as django-cacheops (listed), which has 8x its downloads. +- oobabooga/textgen -- 2026-10-16, no PyPI download signal: A desktop app, not a pip library. PyPI "textgen" is an unrelated package. +- opensanctions/countrynames -- 2026-10-16, 15,360 downloads/month (ClickPy): Narrow job. pycountry (32.2M, unlisted) is the obvious country-data library. +- osantana/prettyconf -- 2026-10-16, 29,957 downloads/month (ClickPy): The use case is full at 5 entries, and prettyconf has about 0.6% of the downloads of dynaconf, the smallest entry. +- pydata/numexpr -- 2026-10-16, 12,883,844 downloads/month (ClickPy): Healthy (2.14.2 released 2026-07), but Core already holds numpy, scipy, and numba with far more demand. numexpr is an older accelerator, not a successor to any of them. +- python-excel/xlrd -- 2026-10-16, 70,465,563 downloads/month (ClickPy): Removed 2026-01-16 (d9bba73) as archived, but the repo was never archived. Releases have not resumed since 2.0.2 (2025-06), its own tagline says to use openpyxl where possible, it reads only legacy .xls, and python-calamine (7.7M) is the recommended replacement. Most of the count is direct demand. +- rajatim/zhtw -- 2026-10-16, 719 downloads/month (ClickPy): 14 stars, created 2025-12. It covers a narrower part of OpenCC's job. +- rushter/MLAlgorithms -- 2026-10-16, no PyPI download signal: Educational code, not on PyPI. thealgorithms already covers this. +- s3tools/s3cmd -- 2026-10-16, 1,243,432 downloads/month (ClickPy): The 2026-03-21 removal (e8d3d29) still holds: last release 2023-12, and it crosses the 12-month activity line on 2026-10-22. awscli and boto3 cover the job. +- saresend/KSUID -- 2026-10-16, 74,743 downloads/month (ClickPy): Fails Active: last commit 2018-11, last release 2017. svix-ksuid (1.0M) is the bigger KSUID library. +- shibing624/text2vec -- 2026-10-16, 2,291 downloads/month (ClickPy): sentence-transformers (listed) covers this, and there is no independent demand. +- smartcrop/smartcrop.py -- 2026-10-16, 29,956 downloads/month (ClickPy): A niche content-aware cropping job at 30K, and General is at cap (floor: pyvips, 867,739). +- SmileyChris/easy-thumbnails -- 2026-10-16, 469,327 downloads/month (ClickPy): Django-specific and below General's floor, with no lead over sorl-thumbnail. Last release 2025-08. +- ssut/py-googletrans -- 2026-10-16, 1,941,718 downloads/month (ClickPy): Fails Active: last commit 2025-04. It is an unofficial Google Translate scraper (machine translation, not i18n). +- TeamHG-Memex/eli5 -- 2026-10-16, 84,428 downloads/month (ClickPy): Fails Active: the maintained fork eli5-org/eli5 last committed on 2025-04-20, and recent commits to the original repo only delete workflow files. +- TheTom/turboquant_plus -- 2026-10-16, no PyPI download signal: A research repo for KV-cache quantization. Every commit since 2026-06-12 is a README edit, and the latest says the work was merged upstream into mlx-swift-lm. Nothing pip-installable. +- thumbor/libthumbor -- 2026-10-16, 66,538 downloads/month (ClickPy): A companion to the listed thumbor. Last release 2022-03, with only dependabot commits since. +- THUwangcy/ReChorus -- 2026-10-16, no PyPI download signal: An academic research framework with 648 stars, not on PyPI. +- tyiannak/pyAudioAnalysis -- 2026-10-16, 13,577 downloads/month (ClickPy): Removed 2026-03-21 (e8d3d29) as unmaintained, and that still holds: last release 2022-02, with only README edits since. +- uploadcare/pillow-simd -- 2026-10-16, 66,174 downloads/month (ClickPy): A fork of the listed pillow with 0.01% of its downloads, and General is at cap. +- wroberts/pytimeparse -- 2026-10-16, 23,637,352 downloads/month (ClickPy): Its count matches agate's (20.8M), which dbt-core pulls in, so very little of it is people choosing pytimeparse. 1.1.9 is its first release since 2018 and is classified Beta. The use case is full. +- x-hw/amazing-qr -- 2026-10-16, 812 downloads/month (ClickPy): Its 10.8k stars don't show up as installs. It pins Pillow<12, while qrcode (28.7M) holds the use case. +- xhtml2pdf/xhtml2pdf -- 2026-10-16, 3,813,456 downloads/month (ClickPy): It was removed in 2016 (a936fd1) as "deprecated in favor of WeasyPrint", which is no longer true: it shipped 0.2.22–0.2.24 in 2026-10. It still fails the tier bar, since the web calls WeasyPrint the default (32.5M) and describes xhtml2pdf as having limited CSS. It is an older alternative, not a successor. +- Yelp/detect-secrets -- 2026-10-16, 9,698,855 downloads/month (ClickPy): Weak maintenance: last release 2024-05, last code commit 2025-01, and only a CI commit in 2026. Demand rose 6.6x with no explained cause. +- youssofal/MTPLX -- 2026-10-16, 7,276 downloads/month (ClickPy): Narrow: its own summary is "Native MTP speculative decoding for Qwen3-Next on Apple Silicon". Repo created 2026-05-02, and it hard-requires mlx-lm, which is already listed, so it is an add-on rather than a separate pick. +- ytdl-org/youtube-dl -- 2026-10-16, 164,180 downloads/month (ClickPy): The 2026-03-21 removal (f50bd8f, replaced by yt-dlp) still holds: no release since 2021.12.17, commits stopped 2025-11, and downloads are falling. + ## Last Audited An audit that changes nothing in a section leaves no commit, so its date is recorded here, one line per section, replaced on each re-audit. diff --git a/website/data/pypi_name_overrides.json b/website/data/pypi_name_overrides.json index daf57097..0ee6dfa6 100644 --- a/website/data/pypi_name_overrides.json +++ b/website/data/pypi_name_overrides.json @@ -1,6 +1,7 @@ { "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", "badge": "Multiple on PyPI" }, + "betterleaks": { "package": null, "reason": "not published on PyPI" }, "cloud-init": { "package": null, "reason": "installed via distro images, not pip" }, "concurrent-futures": { "package": null, "reason": "stdlib module" }, "conda": { "package": null, "reason": "installed via Miniforge or Anaconda installers; PyPI conda is a stale 2017 upload" }, @@ -16,11 +17,11 @@ "google-cloud-python": { "package": null, "reason": "monorepo umbrella; ships as many google-cloud-* packages", "badge": "Multiple on PyPI" }, "graphify": { "package": "graphifyy", "reason": null }, "httpx-url": { "package": null, "reason": "class in the httpx package, not a package" }, - "jev-ultrafast": { "package": null, "reason": "not published on PyPI" }, "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" }, + "mise": { "package": null, "reason": "not published on PyPI; PyPI mise is an unrelated package" }, "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 }, diff --git a/website/data/redirects.json b/website/data/redirects.json index 51e5593b..d5dc47fd 100644 --- a/website/data/redirects.json +++ b/website/data/redirects.json @@ -1,5 +1,6 @@ { "/categories/": "/", + "/categories/ai-and-agents/llm-inference-and-serving/": "/categories/ai-and-agents/llm-serving/", "/categories/ai-and-agents/pre-trained-models-and-inference/": "/categories/ai-and-agents/pre-trained-models/", "/categories/cli-development/cli-development/": "/categories/cli-development/", "/categories/cli-tools/productivity-tools/": "/categories/cli-tools/",
EntrySourceDownloads/moMy verdictMy reasonYoursYour reason (optional)
${name}${source || ""}${dl} ${mine.toUpperCase()} ${reason} - ${mine === "add" - ? `` - : ``} - + ${CHOICES[mine].map(v => ``).join("")}