pypi-query-mcp/DEV_DEPENDENCIES_IMPLEMENTATION_REPORT.md
Ryan Malloy 29994dd611 feat: add development dependency support to get_package_dependencies
- 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
2025-08-15 11:54:09 -06:00

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

  1. 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
  2. PyPI Metadata Fields:

    • requires_dist: Contains all dependencies including those with extra markers
    • provides_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 dependencies
  • development_optional_dependencies: Development-related optional dependency groups
  • provides_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

  1. No Universal Standard: Not all packages use the extra dependency pattern for development dependencies
  2. Naming Variations: Some packages may use non-standard extra names
  3. Version-Specific: Currently returns dependencies for the latest version only

Implementation Scope

  1. Source Coverage: Only extracts information available in PyPI metadata
  2. Build Dependencies: Build-time dependencies may not be captured if not listed in extras
  3. 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

  1. Use provides_extra field to understand what optional dependencies are available
  2. Check both development_dependencies and development_optional_dependencies for complete picture
  3. Consider installing relevant extras when developing with packages

For Future Enhancements

  1. Add support for querying specific package versions (currently only latest)
  2. Consider adding heuristic detection for non-standard development dependency patterns
  3. Add support for parsing build system dependencies from pyproject.toml metadata when available

Conclusion

The implementation successfully addresses the original issue by:

  1. Correctly parsing extra dependencies from PyPI metadata
  2. Identifying development-related extras using comprehensive keyword matching
  3. Extracting meaningful development dependencies from real packages
  4. Providing enhanced response format with detailed categorization
  5. 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.