A Python dependency analysis tool that detects ghost dependencies, zombie dependencies, and outdated packages in your projects.
- Overview
- Features
- Architecture
- Getting Started
- Usage
- Supported File Formats
- Output Formats
- Project Structure
- Collaborators
Python projects accumulate dependencies over time. Libraries go stale, get abandoned, or stop being used — but they stay in your config files. PyPipMan analyzes your project and tells you exactly what's happening with your dependencies.
Given a Python project directory (or a single dependency/source file), PyPipMan:
- Parses dependency configuration files (
pyproject.toml,requirements.txt,uv.lock,poetry.lock). - Parses all
.pysource files using Python's AST (Abstract Syntax Tree). - Crosses declared dependencies against actual imports found in the code.
- Queries the PyPI REST API at
https://pypi.org/pypi/{package}/json(where{package}is the package name) to check for newer versions. - Reports everything in a graphical dashboard, terminal output, or exported files.
| Feature | Description |
|---|---|
| 👻 Ghost dependencies | Names used in code with no backing import (e.g. requests.get(...) without import requests) |
| 🧟 Zombie dependencies | Imports that exist in the source but are never referenced anywhere |
| 📦 Total dependencies | Full list of dependencies found in config files |
| ❌ Missing dependencies | Modules imported but absent from any config file |
| 🗑️ Unused dependencies | Declared packages not referenced anywhere in the source code |
| 🕰️ Outdated dependencies | Packages with a newer version available on PyPI |
| 🖥️ GUI Dashboard | Interactive Tkinter dashboard with charts, filters, and light/dark themes |
| ⌨️ CLI | Click-based command line with analyze, check, and graph commands |
| 📟 TUI | Arrow-key-navigable terminal menu built with rich and prompt_toolkit |
| 📄 PDF Report | Full PDF report with summary and dependency table |
| 📊 CSV Export | Flat CSV export for tracking dependencies over time |
| 🔗 Dependency Graph | NetworkX graph of file → module relationships |
PyPipMan is organized in layers. Each layer has a single responsibility and communicates with adjacent layers through well-defined interfaces.
| File | Description |
|---|---|
__main__.py |
Enables python -m py_pip_man execution |
__init__.py |
Package metadata (__version__, __author__) |
Located in cli/.
| File | Description |
|---|---|
base.py |
Click command group. Defines analyze, check, graph, menu, and gui commands |
tui.py |
Terminal User Interface built with rich and prompt_toolkit. Interactive arrow-key navigation |
utils.py |
Formatting helpers: colored output, graph plotting with matplotlib, result rendering |
Commands available:
py_pip_man analyze <path> # Analyze a single .py or dependency file
py_pip_man check <path> # Full project analysis (directory)
py_pip_man graph <path> # Build and display the dependency graph
py_pip_man menu # Launch the interactive TUI menu
py_pip_man gui # Launch the graphical dashboard
Located in core/analyzers/.
The coordinator (coordinator.py) is the central orchestrator. It calls parsers, merges observations, runs all analyzers, and assembles the final result dictionary.
Analyzers are split into three sub-packages:
| Sub-package | Analyzer | Description |
|---|---|---|
import_analyzers/ |
ghost_analyzer.py |
Detects names used in code with no backing import |
import_analyzers/ |
zombie_analyzer.py |
Detects imports that are declared but never referenced |
usage_analyzers/ |
ghost_analyzer.py |
Same ghost logic, scoped to a specific file context |
usage_analyzers/ |
zombie_analyzer.py |
Same zombie logic, applied to merged project-wide observations |
package_analyzers/ |
outdated_analyzer.py |
Queries PyPI and compares declared vs. latest versions |
Ghost dependency — a name used in the code that has no import statement behind it. Example: calling requests.get(...) without import requests.
Zombie dependency — an import that exists in the source but is never called or referenced anywhere. Example: import os at the top of a file where os is never used.
Located in core/parsers/.
Split into two sub-packages:
source_code/ — Parses .py files using Python's built-in ast module.
| File | Description |
|---|---|
py_parser.py |
Entry point. Opens a .py file, builds the AST, walks it, and returns an observations dict |
program_structure.py |
Converts the AST into a NetworkX DiGraph for topological traversal |
handlers.py |
AST node handlers (one per node type). Uses a DISPATCH table to map node types to handler functions |
utils.py |
Token validation, graph node helpers, AST argument and target collectors |
The observations dict returned by the source parser contains:
{
"modules": set, # top-level module names from import statements
"bindings": dict, # local_name -> (module, kind)
"symbols": dict, # name -> metadata (file, line, version, ...)
"imported_items": set, # names imported via `from X import Y`
"aliases": dict, # alias -> original module
"locals": set, # locally assigned variable names
"functions": set, # function names defined in the file
"classes": set, # class names defined in the file
"usages": set, # all Name nodes loaded (used) in the file
}dependencies/ — Parses dependency configuration files.
| File | Description |
|---|---|
factory.py |
Dispatch table mapping filenames to parsers. Adding a new format only requires adding one entry here |
requirements_parser.py |
Parses requirements.txt line by line using regex |
toml_parser.py |
Parses pyproject.toml (PEP 621 and Poetry styles) using pytoml |
lock_parser.py |
Parses uv.lock and poetry.lock files (TOML [[package]] blocks) |
All dependency parsers return the same observations dict structure, populating modules and symbols with the package names and versions found.
Located in core/api_wrapper.py.
Thin wrapper around the PyPI REST API at https://pypi.org/pypi/{package}/json.
| Function | Description |
|---|---|
make_api_request(url) |
Sends HTTP GET/POST and returns JSON as dict. Returns {} on any failure |
get_info(package_name, version?) |
Fetches full package info from PyPI |
get_latest_version(package_name) |
Returns the latest version string for a package |
get_attribute(data, attribute) |
Extracts a named field from a PyPI response using PYPI_ATTRIBUTE_MAP |
No hard dependencies beyond requests. Returns empty results gracefully on network failures.
Located in core/output/output_manager.py.
| Function | Description |
|---|---|
save_json_report(results, filepath) |
Saves the full analysis result as JSON |
save_csv_report(results, filepath) |
Flattens all sections into a single CSV |
save_multiple_csv_reports(results, filepath) |
One CSV file per section (ghost, zombie, etc.) |
export_results(results, filepath, format_type) |
Dispatcher: calls JSON or CSV saver based on format_type |
Located in gui/. The GUI is split into focused modules so that layout, styling, state, and side-effect actions each live in their own file.
| File | Description |
|---|---|
dashboard.py |
Entry point. Initializes the Tkinter root window and starts the main loop |
components.py |
Layout builders for the header, upload card, metric cards, filter tabs, and table |
constants.py |
Colors, fonts, and theme definitions (dark and light, selected via PYPIPMAN_THEME) |
state.py |
Centralized state dict holding references to widgets and current analysis data |
ttk_style.py |
Styling for ttk widgets (Treeview heading, scrollbar) |
services.py |
Data shaping: turns analysis results into table rows and counters |
file_utils.py |
Cross-platform helpers to open files with the system default application |
report_pdf.py |
ReportLab PDF generator with header, summary counters, table, and graph info |
actions/ |
Side-effect functions triggered by buttons (analysis, filtering, exports, charts) |
The actions/ sub-package contains:
| File | Description |
|---|---|
analysis_actions.py |
analyze_file_action, analyze_project_action, run_analysis, process_analysis_result |
view_actions.py |
update_metrics, update_filter_labels, fill_table, apply_filter, update_path_label |
chart_actions.py |
update_chart — renders a matplotlib horizontal bar chart inside the dashboard |
export_actions.py |
export_csv, export_report (PDF) — open save dialogs and write to disk |
The dashboard uses a centralized state dict pattern. All UI components read from and write to state, which avoids passing widget references between functions.
Key entry points:
| Function | Location | Description |
|---|---|---|
start_gui() |
dashboard.py |
Initializes and runs the Tkinter main loop |
run_analysis() |
actions/analysis_actions.py |
Calls analyze_file or analyze_project and feeds results into the UI |
process_analysis_result(...) |
actions/analysis_actions.py |
Updates state, metrics, table rows, and labels after analysis |
apply_filter(key) |
actions/view_actions.py |
Switches between dependency categories (all, ghost, zombie, etc.) |
export_csv() |
actions/export_actions.py |
Opens a save dialog and writes the current rows to CSV |
export_report() |
actions/export_actions.py |
Opens a save dialog and generates a PDF via report_pdf.py |
update_chart() |
actions/chart_actions.py |
Renders a matplotlib horizontal bar chart inside the dashboard |
- Python 3.12 or higher
uv(recommended) orpip
1. Clone the repository:
git clone https://gitlab.unipampa.edu.br/<your-group>/py_pip_man.git
cd py_pip_man2. Create a virtual environment and install dependencies:
Using uv (recommended):
uv syncUsing pip:
python -m venv .venv
source .venv/bin/activate # Linux/macOS
.venv\Scripts\activate # Windows
pip install -e .3. Verify the installation:
python -m py_pip_man --versionYou should see py_pip_man, version 0.1.0.
Launch the full graphical dashboard:
python -m py_pip_man gui
# Light theme
PYPIPMAN_THEME=light python -m py_pip_man gui
# Dark theme (default)
PYPIPMAN_THEME=dark python -m py_pip_man guiSteps inside the GUI:
- Click Analyze File to select a single
.py,requirements.txt, orpyproject.tomlfile.
Or click Analyze Project to select a project directory. - Click ▶ Analyze to run the analysis.
- Use the filter buttons (All, Ghost, Zombie, Missing, Unused, Outdated, Charts) to explore results.
- Click Export CSV to save the dependency list as a CSV file.
- Click Export Report to save a PDF report with full details.
Analyze a single file:
# Analyze a Python file
python -m py_pip_man analyze path/to/script.py
# Analyze a requirements file
python -m py_pip_man analyze path/to/requirements.txt
# Save output as JSON
python -m py_pip_man analyze path/to/script.py --output result.json
# Save output as CSV
python -m py_pip_man analyze path/to/script.py --output result.csv
# Show the dependency graph in a matplotlib window
python -m py_pip_man analyze path/to/script.py --graphAnalyze a full project directory:
# Full project analysis
python -m py_pip_man check path/to/my_project/ --ignore .venv --ignore tests/
# Save results
python -m py_pip_man check path/to/my_project/ --output report.json
# Show graph summary
python -m py_pip_man check path/to/my_project/ --graphThe check command exits with code 1 if ghost, zombie, or missing dependencies are found. This makes it suitable for use in CI/CD pipelines.
Build and inspect the dependency graph:
# Summary only
python -m py_pip_man graph path/to/my_project/
# Show all nodes
python -m py_pip_man graph path/to/my_project/ --nodes
# Show all edges
python -m py_pip_man graph path/to/my_project/ --edges
# Open matplotlib visualization
python -m py_pip_man graph path/to/my_project/ --graphExample output of check:
Checking project: /home/user/my_project
──────────────────────────────
👻 Ghost Dependencies
──────────────────────────────
(none)
──────────────────────────────
🧟 Zombie Dependencies
──────────────────────────────
• numpy
at: src/utils.py:3
──────────────────────────────
📦 Total Dependencies
──────────────────────────────
• requests
• numpy
• pandas
──────────────────────────────
🕰️ Status Dependencies
──────────────────────────────
• requests
Installed: 2.28.0 | Latest: 2.32.3 -> Status: ❌ outdated
• numpy
Installed: 1.24.0 | Latest: 1.24.0 -> Status: ✅ up to date
Launch the arrow-key-navigable terminal menu:
python -m py_pip_man menuNavigate with ↑ ↓, confirm with Enter, and go back with Escape.
Options available:
- Import directory — analyze a full project
- Import file — analyze a single file
- Settings — configure ignored directories and default output format
- Exit
| File | Parser | Notes |
|---|---|---|
requirements.txt |
requirements_parser.py |
Parses package names and version specifiers |
pyproject.toml |
toml_parser.py |
Supports PEP 621 ([project]) and Poetry ([tool.poetry.dependencies]) |
uv.lock |
lock_parser.py |
Skips editable (project-self) entries |
poetry.lock |
lock_parser.py |
Skips dev category packages |
When analyzing a project directory, PyPipMan reads all supported files it finds. If multiple files are present, they are processed in priority order: pyproject.toml → requirements.txt → poetry.lock → uv.lock.
| Format | Flag / Function | Description |
|---|---|---|
| Terminal | Default | Colored, sectioned output in the terminal |
| JSON | --output result.json |
Full structured result as JSON |
| CSV | --output result.csv |
Flat table with type, name, and metadata columns |
| GUI → Export Report | Formatted PDF report with logo, summary, and table |
The test suite uses pytest and pytest-mock. Tests are organized into:
tests/— unit tests for parsers, analyzers, and the API wrapper.tests/acceptance/cli/— acceptance tests mapped to user stories (US01–US08).
Run the full suite:
pytest tests/Run a specific module:
pytest tests/test_outdated_analyzer.py -vRun only acceptance tests:
pytest tests/acceptance/Generate the acceptance metrics report:
python tests/acceptance/run_metrics.pyThis regenerates tests/acceptance/acceptance_metrics_report.md with execution time and peak memory per user story.
py_pip_man/
├── __init__.py # Package metadata
├── __main__.py # python -m py_pip_man entry point
├── config.py # Global constants (ignored dirs, supported files)
├── utils.py # ZIP extraction and project root helpers
│
├── cli/
│ ├── base.py # Click command group and all CLI commands
│ ├── tui.py # Interactive terminal menu
│ └── utils.py # Output formatting and graph plotting helpers
│
├── core/
│ ├── api_wrapper.py # PyPI REST API client
│ │
│ ├── analyzers/
│ │ ├── coordinator.py # Central orchestrator for all analysis
│ │ ├── import_analyzers/
│ │ │ ├── ghost_analyzer.py # Ghost detection (import level)
│ │ │ └── zombie_analyzer.py # Zombie detection (import level)
│ │ ├── usage_analyzers/
│ │ │ ├── ghost_analyzer.py # Ghost detection (usage/file level)
│ │ │ └── zombie_analyzer.py # Zombie detection (usage/file level)
│ │ └── package_analyzers/
│ │ └── outdated_analyzer.py # PyPI version comparison
│ │
│ ├── output/
│ │ └── output_manager.py # JSON and CSV export
│ │
│ └── parsers/
│ ├── dependencies/
│ │ ├── factory.py # Filename → parser dispatch table
│ │ ├── requirements_parser.py # requirements.txt parser
│ │ ├── toml_parser.py # pyproject.toml parser
│ │ └── lock_parser.py # uv.lock / poetry.lock parser
│ └── source_code/
│ ├── py_parser.py # .py file AST parser
│ ├── program_structure.py # AST → NetworkX graph bridge
│ ├── handlers.py # AST node handlers and DISPATCH table
│ └── utils.py # Token validation and AST helpers
│
└── gui/
├── dashboard.py # Tkinter entry point (start_gui)
├── components.py # Layout builders
├── constants.py # Theme constants (dark/light)
├── state.py # Centralized UI state dict
├── ttk_style.py # ttk widget styling
├── services.py # Result-to-rows data shaping
├── file_utils.py # Cross-platform file-open helpers
├── report_pdf.py # ReportLab PDF report generator
├── logo.png # Application logo
└── actions/
├── analysis_actions.py # File/project analysis triggers
├── view_actions.py # Metrics, labels, table filling
├── chart_actions.py # Matplotlib bar chart rendering
└── export_actions.py # CSV and PDF export dialogs
- Amanda Dias (amandadds.aluno@unipampa.edu.br)
- Diogo Mainart Monteiro (diogomonteiro.aluno@unipampa.edu.br)
- Milena Castro Silva (milenacs2.aluno@unipampa.edu.br)
- Rafaela Pacheco (rafaelanunes.aluno@unipampa.edu.br)
- Roger Barros (rogerbarros.aluno@unipampa.edu.br)
- Vitoria Pereira Garcia (vitoriapg.aluno@unipampa.edu.br)
PyPipMan — Developed as part of the RP-III course (AL0337) at Universidade Federal do Pampa (Unipampa), 2026/1.

