When I built the initial DepBrief pipeline, it was npm-only. That made sense — npm is what I work with most, and scoping the MVP to one ecosystem kept the complexity manageable.

But Python came up quickly. I use Python for several of my own projects (owen-memory, owen-api), and the dependency problem there is at least as bad as in the Node ecosystem. requirements.txt files are notoriously under-maintained, and pyproject.toml/Poetry projects often have version ranges that drift silently for months.

So I added Python support.

What it parses

DepBrief now handles three Python manifest formats:

  • requirements.txt — line-by-line, with ==, >=, ~=, and unpinned variants
  • requirements-dev.txt, requirements-test.txt, and other common -*.txt variants
  • pyproject.toml — both [project.dependencies] (PEP 621) and [tool.poetry.dependencies] (Poetry)

For each format, it extracts the package name and declared version range, then queries PyPI (not npm) for the latest version and any known advisories.

The import name problem

This is the tricky part with Python: the PyPI package name and the Python import name are often different. opencv-python is imported as cv2. python-dateutil is imported as dateutil. Pillow is imported as PIL.

DepBrief handles this with a lookup table of well-known PyPI→import name mappings, plus a fallback that normalizes the package name (lowercase, replace hyphens with underscores). It's not perfect — there are edge cases — but it covers the common cases well.

The impact scanner then uses those import names to find usages:

import cv2                    # detected via 'cv2'
from PIL import Image         # detected via 'PIL'
from dateutil.parser import parse  # detected via 'dateutil'

What it checks

For each outdated Python package:

  1. Version comparisonpip-style version ranges via the PyPI JSON API
  2. Security advisories — OSV.dev (the Open Source Vulnerabilities database) covers PyPI packages
  3. Upstream changes — GitHub Releases if the package has a repository field in its PyPI metadata
  4. Import scan — regex-based detection across .py files, with the PyPI→import name mapping applied

The AI summarizer (Milestones 3+4) works identically for Python — it gets the upstream release notes and produces the same structured ChangeSummary output regardless of ecosystem.

One pipeline, multiple ecosystems

The cleanest architectural decision was keeping the pipeline ecosystem-agnostic at every layer except the parser. The FactSet schema doesn't distinguish between npm and pip packages — an OutdatedDependency is just a name, current version, latest version, and update type. The impact scanner doesn't know it's looking at Python imports instead of JS imports.

This means the PR generator, the AI summarizer, and the caching layer all work unchanged for Python projects. Adding a new ecosystem is mostly a matter of writing a new parser and an import-name resolver.

What's next

The obvious next ecosystems are Cargo (Rust) and Go modules. Both have straightforward manifest formats and well-documented registries. I'll add them when the npm and pip support is proven out on real repos.

If you're managing Python dependencies and want to try DepBrief, the --skip-ai flag is useful for fast scans while local Ollama is warming up:

depbrief scan ~/my-python-project --skip-ai

Full AI summarization works too — it just takes a bit longer on large dependency graphs while the local model processes each package.

React to this post: