- Implement parsing of development dependencies from extra markers - Add comprehensive development keyword detection (20+ patterns) - Enhance response format with dev dependency categorization - Add development_optional_dependencies and provides_extra fields - Test with pytest, setuptools, sphinx, wheel packages
6.9 KiB
Development Dependencies Implementation Report
Summary
Successfully implemented comprehensive development dependency support for the get_package_dependencies
tool. The implementation now correctly identifies and categorizes development dependencies from PyPI package metadata.
Problem Analysis
Original Issue
The original implementation showed empty development dependency arrays for all tested packages because it used overly simplistic parsing logic that only looked for "dev" or "test" keywords in dependency strings.
Root Cause
Development dependencies in Python packages are primarily specified through extra dependencies (optional dependencies) rather than separate metadata fields. The PyPI API provides this information in the requires_dist
field with markers like extra == "dev"
, extra == "test"
, etc.
Key Findings
How Development Dependencies Are Specified
-
Extra Dependencies: Most development dependencies are specified as optional extras in
requires_dist
- Format:
dependency-name>=version; extra == "dev"
- Common extra names:
dev
,test
,doc
,lint
,build
,check
,cover
,type
- Format:
-
PyPI Metadata Fields:
requires_dist
: Contains all dependencies including those with extra markersprovides_extra
: Lists available extra names that can be installed
Examples from Real Packages
pytest (8.4.1):
- 7 runtime dependencies, 7 development dependencies
- Development dependencies from
extra == "dev"
: argcomplete, attrs, hypothesis, mock, requests, setuptools, xmlschema
setuptools (80.9.0):
- 0 runtime dependencies, 41 development dependencies
- Development extras: test, doc, check, cover, type
- Example dev deps: pytest, sphinx, ruff, mypy
sphinx (8.2.3):
- 17 runtime dependencies, 21 development dependencies
- Development extras: docs, lint, test
- Example dev deps: sphinxcontrib-websupport, ruff, mypy
Implementation Changes
1. Enhanced DependencyParser.categorize_dependencies()
Before:
# Only looked for keywords in dependency strings
if any(keyword in marker_str.lower() for keyword in ["dev", "test", "lint", "doc"]):
categories["development"].append(req)
After:
# Properly parse extra markers and check against comprehensive dev extra names
if "extra ==" in marker_str:
extra_match = re.search(r'extra\s*==\s*["\']([^"\']+)["\']', marker_str)
if extra_match:
extra_name = extra_match.group(1)
if extra_name.lower() in dev_extra_names:
categories["development"].append(req)
2. Comprehensive Development Extra Detection
Added comprehensive list of development-related extra names:
- Core:
dev
,development
- Testing:
test
,testing
,tests
- Documentation:
doc
,docs
,documentation
- Code Quality:
lint
,linting
,check
,style
,format
,quality
- Build/Type:
build
,type
,typing
,mypy
- Coverage:
cover
,coverage
3. Enhanced Response Format
New fields added:
development_dependencies
: List of development dependenciesdevelopment_optional_dependencies
: Development-related optional dependency groupsprovides_extra
: List of available extras from package metadata- Enhanced
dependency_summary
with dev-specific counts
4. Improved Categorization
Development dependencies are now properly separated into:
- Runtime dependencies: No extra markers
- Development dependencies: Dependencies with dev-related extra markers
- Optional dependencies: Non-development extra dependencies
- Development optional dependencies: Development-related extra groups
Testing Results
Before Implementation
pytest: 0 development dependencies
setuptools: 0 development dependencies
sphinx: 0 development dependencies
After Implementation
pytest: 7 development dependencies (from extra == "dev")
setuptools: 41 development dependencies (from test/doc/check/cover/type extras)
sphinx: 21 development dependencies (from docs/lint/test extras)
wheel: 2 development dependencies (from test extra)
Success Rate
- Tested 8 development-focused packages
- 4/8 packages (50%) had identifiable development dependencies
- Successfully extracted 71 total development dependencies across all packages
API Response Examples
Enhanced Response Format
{
"package_name": "pytest",
"version": "8.4.1",
"runtime_dependencies": ["colorama>=0.4; sys_platform == \"win32\"", "..."],
"development_dependencies": ["argcomplete; extra == \"dev\"", "..."],
"optional_dependencies": {},
"development_optional_dependencies": {
"dev": ["argcomplete; extra == \"dev\"", "attrs>=19.2; extra == \"dev\"", "..."]
},
"provides_extra": ["dev"],
"dependency_summary": {
"runtime_count": 7,
"dev_count": 7,
"optional_groups": 0,
"dev_optional_groups": 1,
"total_optional": 0,
"total_dev_optional": 7
}
}
Limitations and Considerations
PyPI API Limitations
- No Universal Standard: Not all packages use the extra dependency pattern for development dependencies
- Naming Variations: Some packages may use non-standard extra names
- Version-Specific: Currently returns dependencies for the latest version only
Implementation Scope
- Source Coverage: Only extracts information available in PyPI metadata
- Build Dependencies: Build-time dependencies may not be captured if not listed in extras
- Platform Dependencies: Some dev dependencies may be platform-specific
Alternative Sources Considered
- setup.py/pyproject.toml: Not available through PyPI API
- GitHub repositories: Would require additional API calls and parsing
- requirements-dev.txt files: Not standardized or accessible through PyPI
Recommendations
For Users
- Use
provides_extra
field to understand what optional dependencies are available - Check both
development_dependencies
anddevelopment_optional_dependencies
for complete picture - Consider installing relevant extras when developing with packages
For Future Enhancements
- Add support for querying specific package versions (currently only latest)
- Consider adding heuristic detection for non-standard development dependency patterns
- Add support for parsing build system dependencies from pyproject.toml metadata when available
Conclusion
The implementation successfully addresses the original issue by:
- ✅ Correctly parsing extra dependencies from PyPI metadata
- ✅ Identifying development-related extras using comprehensive keyword matching
- ✅ Extracting meaningful development dependencies from real packages
- ✅ Providing enhanced response format with detailed categorization
- ✅ Maintaining backward compatibility while adding new functionality
The solution extracts as much development dependency information as possible from available PyPI metadata, with clear documentation of limitations where the PyPI API doesn't provide sufficient information.