Papers
Topics
Authors
Recent
Search
2000 character limit reached

PyTrim: Automated Removal of Unused Dependencies

Updated 4 July 2026
  • PyTrim is an end-to-end automation tool that removes unused dependencies and associated imports from Python projects across various configuration files.
  • It combines dynamic dependency resolution using pip and pipdeptree with static analysis from multiple detectors to improve recall over traditional methods.
  • The tool supports integration into CI workflows by automatically creating Git branches, commits, and pull requests, thus reducing maintenance overhead.

PyTrim is an end-to-end automation tool for removing unused dependencies from Python projects. It addresses a specific form of dependency bloat in which packages remain declared in configuration files such as requirements.txt, pyproject.toml, or setup.py even though they are no longer used anywhere in the project’s source code, beyond possibly a dead import. The system is designed to bridge the gap between tools that only detect dependency bloat and the subsequent clean-up work that developers would otherwise perform manually across source and configuration files. Its reported scope includes unused import removal, dependency declaration removal across multiple file formats, optional Git and pull-request automation, and a dynamic dependency resolver intended to improve recall beyond static dependency-resolution techniques (Karakatsanis et al., 1 Oct 2025).

1. Problem setting and motivation

In the paper, dependency bloat denotes Python packages that are still declared as dependencies in a project’s configuration files but are no longer used anywhere in the project’s source code, beyond possibly a dead import. This condition arises because projects evolve over time: code is refactored, features are removed or replaced, and the corresponding dependencies may remain declared. The paper also emphasizes that Python projects frequently declare the same dependency in multiple configuration files, and that setup.py can contain arbitrary Python code, including logic that reads external files or computes dependency lists dynamically. These characteristics make reliable project-wide cleanup difficult to perform by hand (Karakatsanis et al., 1 Oct 2025).

The practical consequences identified for this form of bloat are increased maintenance overhead, larger attack surface, and slower pipelines due to additional packages that must be installed and synchronized. PyTrim is positioned as a practical response to these problems. The work builds on prior empirical results, especially Drosos et al. (2024), which studied dependency bloat in Python using call-graph analysis and showed both that unused dependencies are common and that static analyses can miss them. This suggests that automation is needed not only for detection but also for safe, repeatable removal across the full project layout.

A recurring misconception is that dependency cleanup is equivalent to deleting entries from a single requirements file. PyTrim’s design explicitly rejects that simplification: the clean-up target spans Python imports, multiple requirements variants, TOML, YAML, INI/CFG files, and setup.py. Another misconception is that detection alone solves the problem. The system is instead defined by end-to-end execution from dependency resolution and detector integration to file modification and optional pull-request generation (Karakatsanis et al., 1 Oct 2025).

2. Architecture and execution model

PyTrim takes the path to a Python project and executes a three-stage workflow. First, it performs dynamic dependency resolution by installing the project in isolation and deriving the set of actually installed dependencies using pip together with pipdeptree. Second, it runs an external dependency-bloat detector. Third, it removes unused imports and dependency declarations across source and configuration files, and can optionally create a Git branch, commit, Markdown report, and pull request (Karakatsanis et al., 1 Oct 2025).

Its architecture is explicitly modular. The detector layer is detector-agnostic, and the paper reports out-of-the-box support for three detectors: an extended PyCG-based call-graph detector from Drosos et al. (2024), fawltydeps, and deptry. Integration is performed by modifying each tool’s internal dependency resolution so that it operates on the union of the tool’s own static dependency view and PyTrim’s dynamic dependency list. In set notation, if SS is the detector’s statically inferred dependency set and DD is PyTrim’s dynamic dependency set, the effective dependency set is SDS \cup D. The paper presents this union-based strategy as a recall improvement mechanism for cases involving dynamic setup.py logic, pyproject.toml edge cases, or bugs and limitations in static parsing (Karakatsanis et al., 1 Oct 2025).

The dynamic resolver is central to this architecture. PyTrim performs a source installation by invoking pip with the -t flag to install artifacts into a dedicated directory. It then uses pipdeptree to construct a directed dependency graph in which vertices are installed packages and an edge xyx \rightarrow y indicates that package xx depends on package yy. The project under analysis appears as the node with no incoming edges; its immediate outgoing edges are treated as its direct dependencies. Because this stage runs the actual installation logic, it does not suffer from static parsing limitations associated with dynamically constructed install_requires expressions and requires no manual configuration of dependency declaration mechanisms. The paper simultaneously identifies a boundary condition: only the default installation path is exercised, not optional extras or environment-specific branches (Karakatsanis et al., 1 Oct 2025).

PyTrim can be invoked in two operating modes. In end-to-end mode it resolves dependencies, runs a detector, and performs removals. In removal-only mode it accepts an externally supplied list of unused packages and performs only the file modifications. This separation is significant because it allows the remover to be evaluated independently of detection quality and also enables integration into CI or maintenance workflows in which another detector is already in use.

3. Static and dynamic transformation mechanisms

The remover component accepts a project path and a list of unused dependency packages, such as ["prettytable", "cryptography"], and removes dependency declarations and import statements across multiple file types. The transformation strategy is file-type-specific and generally conservative, with structured parsing preferred over purely textual rewriting (Karakatsanis et al., 1 Oct 2025).

For Python source files, PyTrim parses each .py file into a Python AST, identifies import nodes such as import x and from x import y whose module or top-level package matches an unused dependency, and removes those import statements. The AST-based approach is described as preserving syntactic correctness and distinguishing imports from comments or strings. The detector, not the remover, is responsible for deciding that a package is unused; PyTrim’s responsibility is the corresponding cleanup.

For configuration files, the implementation varies by format. TOML files such as pyproject.toml are parsed using a TOML library, with dependency entries removed from relevant sections such as [project.dependencies] and [tool.poetry.dependencies]. YAML is parsed via PyYAML, INI/CFG files via configparser, and line-based files such as requirements.txt and .in variants are processed line by line, often using regular expressions to remove lines whose base package name corresponds to an unused dependency. setup.py is parsed using AST analysis, with PyTrim locating constructs that define install_requires or equivalent lists and removing elements corresponding to unused dependencies. The paper characterizes this as avoiding execution of arbitrary setup.py code while still handling many static and deterministic patterns (Karakatsanis et al., 1 Oct 2025).

File type Handling strategy
.py AST-based import removal
requirements*.txt, .in Line-based processing
pyproject.toml and other TOML Parsed and rewritten
YAML Parsed via PyYAML
INI/CFG Parsed with configparser
setup.py AST-based dependency-list manipulation

PyTrim does not treat all artifacts as safe rewrite targets. Lock files such as poetry.lock are not automatically regenerated; instead, PyTrim prints a message instructing the user to regenerate them manually when configuration changes may have made them stale. Shell scripts, Dockerfiles, and similar files are only analyzed for reporting and are not modified automatically because their syntax and semantics are considered too varied and fragile for generic safe manipulation. The system also does not attempt semantic refactorings such as converting pyjwt to pyjwt[crypto], changing optional extras, or restructuring program logic. This suggests a strict division between syntactic dependency cleanup and broader semantic maintenance tasks.

4. Evaluation and empirical findings

The evaluation reported in the paper has three distinct parts: dynamic dependency-resolution assessment, remover-effectiveness measurement against human-created pull requests, and real-world deployment on open-source projects (Karakatsanis et al., 1 Oct 2025).

For dynamic dependency resolution, the dataset consisted of 1300 popular GitHub projects from Drosos et al. (2024), of which 971 could be successfully installed and were evaluated. On these 971 projects, PyTrim’s dynamic resolver uncovered missed dependencies in 48 projects, approximately 5%5\%, that the static resolvers inside the compared tools did not detect. The reported reasons were 18 cases of parsing limitations for edge cases in declarative files, 22 cases involving arbitrary setup.py code, and 8 cases due to miscellaneous bugs. The paper gives optimizely-sdk as an example: its install_requires is built by reading reqs/core.txt, which caused static tools to miss the pyrsistent dependency, whereas the dynamic resolver detected it (Karakatsanis et al., 1 Oct 2025).

For remover effectiveness, the ground truth was a curated set of pull requests from prior work in which developers had manually removed bloated dependencies from open-source Python projects. The evaluation procedure deliberately isolated the remover by running PyTrim in removal-only mode on the pre-PR project state while supplying the ground-truth list of dependencies to remove. PyTrim’s outputs were then compared to the final versions of files in the human pull requests, ignoring non-semantic differences such as whitespace and comments. Across 37 pull requests, 76 files had dependency-related changes, 16 files were excluded, and 60 relevant files remained. PyTrim correctly replicated 59 of those 60 files, corresponding to a replication accuracy of 59/6098.33%59/60 \approx 98.33\%. With a precomputed list of unused dependencies, it processed all 37 projects in less than 10 seconds (Karakatsanis et al., 1 Oct 2025).

The single mismatch occurred in simple-salesforce. In that pull request, the human change set both removed cryptography and refactored pyjwt to pyjwt[crypto] to preserve optional crypto features. PyTrim correctly removed cryptography but did not perform the pyjwt refactoring. The paper treats this as evidence that PyTrim focuses on removing unused dependencies rather than performing semantic refactoring.

The real-world deployment used the same 971 installable projects, with the call-graph-based detector as default. After automated changes, all modifications were manually inspected, and pull requests were submitted when the changes were judged valid. PyTrim found and removed unused dependencies in 39 projects, producing 39 pull requests. At the time of writing, 6 had been merged, 29 were under review, and 4 had been closed for project-specific reasons. The softlayer-python case is representative: PyTrim detected prettytable as unused, removed its declarations from setup.py and three separate requirements.txt files, and flagged an occurrence in README.rst for manual review; after the README change was handled by a human, the pull request was merged (Karakatsanis et al., 1 Oct 2025).

Evaluation setting Reported result
Dynamic resolver on 971 installable projects 48 projects with missed dependencies uncovered
Human-PR replication 59 of 60 relevant files correctly replicated
Real-world deployment 39 pull requests created, 6 merged

5. Operational workflow and practical adoption

PyTrim is available as a PyPI package installable with pip install pytrim, and as a command-line tool invoked as pytrim. The paper also identifies an open-source code repository at https://github.com/TrimTeam/PyTrim and a video demonstration at https://youtu.be/LqTEdOUbJRI. Its intended operational model is a review-and-merge workflow rather than autonomous, unreviewed repository modification (Karakatsanis et al., 1 Oct 2025).

In end-to-end usage, PyTrim installs the project in isolation, runs the configured detector or detectors, removes unused dependencies and imports, and can optionally create a branch, commit, and pull request accompanied by a Markdown report. In removal-only mode, it accepts a project path and a list of packages to be removed, making it suitable for workflows in which a separate detector or CI stage already identifies unused dependencies. The paper explicitly presents CI integration as a use case: a detector may run periodically, its output may feed PyTrim in removal-only mode, and PyTrim may then create a branch and pull request for human review.

The practical significance of this workflow lies in the fact that the system handles multiplicity of declaration sites and heterogeneous configuration formats in a single pass. The example of softlayer-python, where declarations were removed from both setup.py and multiple requirements files, illustrates that the tool is designed for project-wide consistency rather than single-file editing. This suggests that PyTrim’s main contribution is operational integration across detection, transformation, and maintenance lifecycle automation, rather than a new detection-only algorithm.

The paper defines several explicit limitations. Dynamic dependency resolution exercises only the default installation path, so optional extras, alternative build configurations, and environment-specific branches are not explored automatically. Lock files are not regenerated. Shell scripts, Dockerfiles, and other unstructured files are not auto-modified. Dynamic imports and subtle usage patterns may still lead to misclassification if neither static analysis nor call-graph-based analysis plus tests can observe the dependency. The paper notes that it did not observe problematic cases in which a package’s import-time side effects were essential to program logic, but it acknowledges the possibility (Karakatsanis et al., 1 Oct 2025).

These limitations separate PyTrim from broader program-repair or refactoring systems. It is not intended to replace domain-aware maintenance decisions, and it does not attempt code restructuring or dependency substitution. The simple-salesforce case makes this distinction concrete: removal of an unused dependency fell within scope, whereas the transformation of pyjwt into pyjwt[crypto] did not.

PyTrim is also situated relative to two categories of existing Python tooling. File-level linters such as autoflake and pylint detect unused imports in .py files, and some can remove such imports from source, but they do not handle project-level dependencies or update configuration files. Project-level dependency analyzers such as deptry and FawltyDeps compare declared dependencies against imported modules in source code and identify unused packages, but they do not remove import statements from code or automatically update configuration files. PyTrim is described as novel in combining detector integration, a dynamic dependency resolver based on actual installation and pipdeptree, broad multi-file removal logic, and branch/commit/pull-request automation in a single end-to-end pipeline (Karakatsanis et al., 1 Oct 2025).

A plausible implication is that PyTrim occupies a systems-integration niche within Python software maintenance research: it converts dependency-bloat detection from an advisory activity into a largely automatable maintenance workflow, while retaining a conservative review boundary around semantically riskier changes.

Definition Search Book Streamline Icon: https://streamlinehq.com
References (1)

Topic to Video (Beta)

No one has generated a video about this topic yet.

Whiteboard

No one has generated a whiteboard explanation for this topic yet.

Follow Topic

Get notified by email when new papers are published related to PYTRIM.