| """Read dependency manifests and explain each library in plain English. |
| |
| A non-coder has no idea what `chromadb` or `axios` is. We parse |
| requirements.txt / package.json / pyproject.toml and attach a one-line, |
| jargon-free description from a curated map (with a generic fallback). No model |
| call needed for the common case. |
| """ |
| from __future__ import annotations |
|
|
| import json |
| import re |
|
|
| from schema import Dependency |
|
|
| |
| |
| KNOWN: dict[str, str] = { |
| |
| "openai": "Talks to OpenAI's AI models (like ChatGPT) to generate text.", |
| "anthropic": "Talks to Anthropic's Claude AI models to generate text.", |
| "langchain": "A toolkit for chaining AI steps together (load β search β answer).", |
| "langchain-community": "Extra connectors for LangChain (databases, loaders, tools).", |
| "llama-index": "Helps an AI answer questions over your own documents.", |
| "transformers": "Runs open-source AI models on your own machine.", |
| "sentence-transformers": "Turns text into numbers (embeddings) so it can be searched by meaning.", |
| "chromadb": "A 'memory' database that stores text as numbers for fast meaning-search.", |
| "faiss-cpu": "A fast search engine for finding similar pieces of text by meaning.", |
| "tiktoken": "Counts how many tokens (word-pieces) your text uses for an AI model.", |
| "huggingface-hub": "Downloads AI models and datasets from Hugging Face.", |
| "gradio": "Builds the web interface you click on, with very little code.", |
| "streamlit": "Builds a simple data web app you click on.", |
| |
| "flask": "A small web server β handles requests from the browser.", |
| "fastapi": "A modern web server for building fast APIs.", |
| "django": "A big all-in-one web framework (pages, database, admin).", |
| "uvicorn": "Runs FastAPI apps and serves them to the browser.", |
| "requests": "Fetches things from the internet (calls other websites/APIs).", |
| "httpx": "Fetches things from the internet, with async support.", |
| "aiohttp": "Fetches things from the internet without waiting (async).", |
| "express": "A small web server for Node.js β handles browser requests.", |
| "axios": "Fetches things from the internet from the browser or Node.", |
| "next": "A React framework for full websites (pages + server).", |
| "react": "Builds interactive user interfaces in the browser.", |
| "react-dom": "Connects React to the actual web page.", |
| "vue": "Builds interactive user interfaces in the browser.", |
| |
| "pandas": "Works with tables of data (like a spreadsheet in code).", |
| "numpy": "Does fast math on big lists of numbers.", |
| "pydantic": "Checks that data has the right shape and types.", |
| "sqlalchemy": "Talks to databases using Python instead of raw SQL.", |
| "psycopg2": "Connects Python to a PostgreSQL database.", |
| "psycopg2-binary": "Connects Python to a PostgreSQL database.", |
| "pymongo": "Connects Python to a MongoDB database.", |
| "redis": "Talks to Redis, a very fast in-memory store/cache.", |
| |
| "pillow": "Opens and edits images.", |
| "pypdf": "Reads text out of PDF files.", |
| "pypdf2": "Reads text out of PDF files.", |
| "python-docx": "Reads and writes Word documents.", |
| "beautifulsoup4": "Pulls data out of web pages (HTML).", |
| "opencv-python": "Computer vision β works with images and video.", |
| |
| "python-dotenv": "Loads secret settings from a .env file.", |
| "dotenv": "Loads secret settings from a .env file.", |
| "tqdm": "Shows a progress bar while something runs.", |
| "click": "Builds command-line tools.", |
| "pytest": "Runs your automated tests.", |
| "modal": "Runs your code on cloud GPUs without managing servers.", |
| "lodash": "A grab-bag of handy helper functions for JavaScript.", |
| "dotenv-flow": "Loads secret settings from .env files.", |
| } |
|
|
| |
| RISKY = { |
| "psycopg2": "Prefer the maintained build 'psycopg2-binary' or 'psycopg[binary]'.", |
| "pypdf2": "PyPDF2 is deprecated β 'pypdf' is the maintained successor.", |
| "request": "Looks like a typo for 'requests'.", |
| } |
|
|
| _REQ_LINE = re.compile(r"^\s*([A-Za-z0-9_.\-]+)") |
|
|
|
|
| def _plain(name: str) -> str: |
| return KNOWN.get(name.lower(), f"A library called '{name}'. Used somewhere in the project.") |
|
|
|
|
| def _dep(name: str, manifest: str) -> Dependency: |
| low = name.lower() |
| return Dependency(name=name, manifest=manifest, plain=_plain(name), |
| risky=low in RISKY) |
|
|
|
|
| def parse_requirements(text: str, manifest: str = "requirements.txt") -> list[Dependency]: |
| out: list[Dependency] = [] |
| for line in text.splitlines(): |
| line = line.strip() |
| if not line or line.startswith(("#", "-")): |
| continue |
| m = _REQ_LINE.match(line) |
| if m: |
| out.append(_dep(m.group(1), manifest)) |
| return out |
|
|
|
|
| def parse_package_json(text: str, manifest: str = "package.json") -> list[Dependency]: |
| out: list[Dependency] = [] |
| try: |
| data = json.loads(text) |
| except (json.JSONDecodeError, ValueError): |
| return out |
| for key in ("dependencies", "devDependencies"): |
| for name in (data.get(key) or {}): |
| out.append(_dep(name, manifest)) |
| return out |
|
|
|
|
| def parse_pyproject(text: str, manifest: str = "pyproject.toml") -> list[Dependency]: |
| """Cheap TOML scan β avoids a tomllib dependency for one simple need.""" |
| out: list[Dependency] = [] |
| |
| for block in re.findall(r"dependencies\s*=\s*\[(.*?)\]", text, re.DOTALL): |
| for item in re.findall(r"['\"]([A-Za-z0-9_.\-]+)", block): |
| out.append(_dep(item, manifest)) |
| |
| poetry = re.search(r"\[tool\.poetry\.dependencies\](.*?)(?:\n\[|\Z)", text, re.DOTALL) |
| if poetry: |
| for name in re.findall(r"^\s*([A-Za-z0-9_.\-]+)\s*=", poetry.group(1), re.MULTILINE): |
| if name.lower() != "python": |
| out.append(_dep(name, manifest)) |
| return out |
|
|
|
|
| def parse_manifest(filename: str, text: str) -> list[Dependency]: |
| base = filename.lower() |
| if base == "requirements.txt": |
| return parse_requirements(text, filename) |
| if base == "package.json": |
| return parse_package_json(text, filename) |
| if base == "pyproject.toml": |
| return parse_pyproject(text, filename) |
| return [] |
|
|