style: fix code formatting and linting issues
- Fix whitespace in docstrings and blank lines - Remove unused variables in tests - Rename unused loop variables to follow conventions - All ruff checks now pass Signed-off-by: Hal <hal.long@outlook.com>
This commit is contained in:
parent
6b14ff6da5
commit
f2b92ff0ee
@ -28,13 +28,13 @@ async def analyze_pyside2_dependencies():
|
|||||||
)
|
)
|
||||||
|
|
||||||
print(f"✅ Successfully resolved dependencies for {result['package_name']}")
|
print(f"✅ Successfully resolved dependencies for {result['package_name']}")
|
||||||
print(f"📊 Summary:")
|
print("📊 Summary:")
|
||||||
summary = result['summary']
|
summary = result['summary']
|
||||||
print(f" - Total packages: {summary['total_packages']}")
|
print(f" - Total packages: {summary['total_packages']}")
|
||||||
print(f" - Runtime dependencies: {summary['total_runtime_dependencies']}")
|
print(f" - Runtime dependencies: {summary['total_runtime_dependencies']}")
|
||||||
print(f" - Max depth: {summary['max_depth']}")
|
print(f" - Max depth: {summary['max_depth']}")
|
||||||
|
|
||||||
print(f"\n📦 Package list:")
|
print("\n📦 Package list:")
|
||||||
for i, pkg in enumerate(summary['package_list'][:10], 1): # Show first 10
|
for i, pkg in enumerate(summary['package_list'][:10], 1): # Show first 10
|
||||||
print(f" {i}. {pkg}")
|
print(f" {i}. {pkg}")
|
||||||
|
|
||||||
@ -66,8 +66,8 @@ async def download_pyside2_packages():
|
|||||||
max_depth=2 # Limit depth for demo
|
max_depth=2 # Limit depth for demo
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f"✅ Download completed!")
|
print("✅ Download completed!")
|
||||||
print(f"📊 Download Summary:")
|
print("📊 Download Summary:")
|
||||||
summary = result['summary']
|
summary = result['summary']
|
||||||
print(f" - Total packages: {summary['total_packages']}")
|
print(f" - Total packages: {summary['total_packages']}")
|
||||||
print(f" - Successful downloads: {summary['successful_downloads']}")
|
print(f" - Successful downloads: {summary['successful_downloads']}")
|
||||||
@ -77,7 +77,7 @@ async def download_pyside2_packages():
|
|||||||
print(f" - Download directory: {summary['download_directory']}")
|
print(f" - Download directory: {summary['download_directory']}")
|
||||||
|
|
||||||
if result['failed_downloads']:
|
if result['failed_downloads']:
|
||||||
print(f"\n⚠️ Failed downloads:")
|
print("\n⚠️ Failed downloads:")
|
||||||
for failure in result['failed_downloads']:
|
for failure in result['failed_downloads']:
|
||||||
print(f" - {failure['package']}: {failure['error']}")
|
print(f" - {failure['package']}: {failure['error']}")
|
||||||
|
|
||||||
@ -104,10 +104,10 @@ async def analyze_small_package():
|
|||||||
print(f"✅ Successfully resolved dependencies for {result['package_name']}")
|
print(f"✅ Successfully resolved dependencies for {result['package_name']}")
|
||||||
|
|
||||||
# Show detailed dependency tree
|
# Show detailed dependency tree
|
||||||
print(f"\n🌳 Dependency Tree:")
|
print("\n🌳 Dependency Tree:")
|
||||||
dependency_tree = result['dependency_tree']
|
dependency_tree = result['dependency_tree']
|
||||||
|
|
||||||
for pkg_name, pkg_info in dependency_tree.items():
|
for _pkg_name, pkg_info in dependency_tree.items():
|
||||||
indent = " " * pkg_info['depth']
|
indent = " " * pkg_info['depth']
|
||||||
print(f"{indent}- {pkg_info['name']} ({pkg_info['version']})")
|
print(f"{indent}- {pkg_info['name']} ({pkg_info['version']})")
|
||||||
|
|
||||||
@ -143,12 +143,12 @@ async def main():
|
|||||||
print("✨ Demo completed!")
|
print("✨ Demo completed!")
|
||||||
|
|
||||||
if click_result:
|
if click_result:
|
||||||
print(f"📝 Click analysis saved to: click_dependencies.json")
|
print("📝 Click analysis saved to: click_dependencies.json")
|
||||||
with open("click_dependencies.json", "w") as f:
|
with open("click_dependencies.json", "w") as f:
|
||||||
json.dump(click_result, f, indent=2)
|
json.dump(click_result, f, indent=2)
|
||||||
|
|
||||||
if pyside2_result:
|
if pyside2_result:
|
||||||
print(f"📝 PySide2 analysis saved to: pyside2_dependencies.json")
|
print("📝 PySide2 analysis saved to: pyside2_dependencies.json")
|
||||||
with open("pyside2_dependencies.json", "w") as f:
|
with open("pyside2_dependencies.json", "w") as f:
|
||||||
json.dump(pyside2_result, f, indent=2)
|
json.dump(pyside2_result, f, indent=2)
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
"""Dependency parsing utilities for PyPI packages."""
|
"""Dependency parsing utilities for PyPI packages."""
|
||||||
|
|
||||||
import re
|
|
||||||
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
||||||
from packaging.requirements import Requirement
|
|
||||||
from packaging.specifiers import SpecifierSet
|
|
||||||
from packaging.version import Version
|
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from packaging.requirements import Requirement
|
||||||
|
from packaging.version import Version
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -14,9 +14,9 @@ class DependencyParser:
|
|||||||
"""Parser for Python package dependencies."""
|
"""Parser for Python package dependencies."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.parsed_cache: Dict[str, List[Requirement]] = {}
|
self.parsed_cache: dict[str, list[Requirement]] = {}
|
||||||
|
|
||||||
def parse_requirements(self, requires_dist: List[str]) -> List[Requirement]:
|
def parse_requirements(self, requires_dist: list[str]) -> list[Requirement]:
|
||||||
"""Parse requirements from requires_dist list.
|
"""Parse requirements from requires_dist list.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -42,9 +42,9 @@ class DependencyParser:
|
|||||||
|
|
||||||
def filter_requirements_by_python_version(
|
def filter_requirements_by_python_version(
|
||||||
self,
|
self,
|
||||||
requirements: List[Requirement],
|
requirements: list[Requirement],
|
||||||
python_version: str
|
python_version: str
|
||||||
) -> List[Requirement]:
|
) -> list[Requirement]:
|
||||||
"""Filter requirements based on Python version.
|
"""Filter requirements based on Python version.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -99,8 +99,8 @@ class DependencyParser:
|
|||||||
|
|
||||||
def categorize_dependencies(
|
def categorize_dependencies(
|
||||||
self,
|
self,
|
||||||
requirements: List[Requirement]
|
requirements: list[Requirement]
|
||||||
) -> Dict[str, List[Requirement]]:
|
) -> dict[str, list[Requirement]]:
|
||||||
"""Categorize dependencies into runtime, development, and optional groups.
|
"""Categorize dependencies into runtime, development, and optional groups.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -142,7 +142,7 @@ class DependencyParser:
|
|||||||
|
|
||||||
return categories
|
return categories
|
||||||
|
|
||||||
def extract_package_names(self, requirements: List[Requirement]) -> Set[str]:
|
def extract_package_names(self, requirements: list[Requirement]) -> set[str]:
|
||||||
"""Extract package names from requirements.
|
"""Extract package names from requirements.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -153,7 +153,7 @@ class DependencyParser:
|
|||||||
"""
|
"""
|
||||||
return {req.name.lower() for req in requirements}
|
return {req.name.lower() for req in requirements}
|
||||||
|
|
||||||
def get_version_constraints(self, req: Requirement) -> Dict[str, Any]:
|
def get_version_constraints(self, req: Requirement) -> dict[str, Any]:
|
||||||
"""Get version constraints from a requirement.
|
"""Get version constraints from a requirement.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
"""Dependency resolution tools for PyPI packages."""
|
"""Dependency resolution tools for PyPI packages."""
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, List, Optional, Set
|
from typing import Any
|
||||||
from packaging.requirements import Requirement
|
|
||||||
|
|
||||||
from ..core import PyPIClient, PyPIError
|
from ..core import PyPIClient, PyPIError
|
||||||
from ..core.dependency_parser import DependencyParser
|
from ..core.dependency_parser import DependencyParser
|
||||||
from ..core.exceptions import InvalidPackageNameError, NetworkError, PackageNotFoundError
|
from ..core.exceptions import (
|
||||||
|
InvalidPackageNameError,
|
||||||
|
NetworkError,
|
||||||
|
PackageNotFoundError,
|
||||||
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -18,16 +20,16 @@ class DependencyResolver:
|
|||||||
def __init__(self, max_depth: int = 10):
|
def __init__(self, max_depth: int = 10):
|
||||||
self.max_depth = max_depth
|
self.max_depth = max_depth
|
||||||
self.parser = DependencyParser()
|
self.parser = DependencyParser()
|
||||||
self.resolved_cache: Dict[str, Dict[str, Any]] = {}
|
self.resolved_cache: dict[str, dict[str, Any]] = {}
|
||||||
|
|
||||||
async def resolve_dependencies(
|
async def resolve_dependencies(
|
||||||
self,
|
self,
|
||||||
package_name: str,
|
package_name: str,
|
||||||
python_version: Optional[str] = None,
|
python_version: str | None = None,
|
||||||
include_extras: Optional[List[str]] = None,
|
include_extras: list[str] | None = None,
|
||||||
include_dev: bool = False,
|
include_dev: bool = False,
|
||||||
max_depth: Optional[int] = None
|
max_depth: int | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Resolve all dependencies for a package recursively.
|
"""Resolve all dependencies for a package recursively.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -49,7 +51,7 @@ class DependencyResolver:
|
|||||||
logger.info(f"Resolving dependencies for {package_name} (Python {python_version})")
|
logger.info(f"Resolving dependencies for {package_name} (Python {python_version})")
|
||||||
|
|
||||||
# Track visited packages to avoid circular dependencies
|
# Track visited packages to avoid circular dependencies
|
||||||
visited: Set[str] = set()
|
visited: set[str] = set()
|
||||||
dependency_tree = {}
|
dependency_tree = {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -90,11 +92,11 @@ class DependencyResolver:
|
|||||||
async def _resolve_recursive(
|
async def _resolve_recursive(
|
||||||
self,
|
self,
|
||||||
package_name: str,
|
package_name: str,
|
||||||
python_version: Optional[str],
|
python_version: str | None,
|
||||||
include_extras: List[str],
|
include_extras: list[str],
|
||||||
include_dev: bool,
|
include_dev: bool,
|
||||||
visited: Set[str],
|
visited: set[str],
|
||||||
dependency_tree: Dict[str, Any],
|
dependency_tree: dict[str, Any],
|
||||||
current_depth: int,
|
current_depth: int,
|
||||||
max_depth: int
|
max_depth: int
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -188,7 +190,7 @@ class DependencyResolver:
|
|||||||
logger.error(f"Error resolving {package_name}: {e}")
|
logger.error(f"Error resolving {package_name}: {e}")
|
||||||
# Continue with other dependencies
|
# Continue with other dependencies
|
||||||
|
|
||||||
def _generate_dependency_summary(self, dependency_tree: Dict[str, Any]) -> Dict[str, Any]:
|
def _generate_dependency_summary(self, dependency_tree: dict[str, Any]) -> dict[str, Any]:
|
||||||
"""Generate summary statistics for the dependency tree."""
|
"""Generate summary statistics for the dependency tree."""
|
||||||
|
|
||||||
total_packages = len(dependency_tree)
|
total_packages = len(dependency_tree)
|
||||||
@ -218,11 +220,11 @@ class DependencyResolver:
|
|||||||
|
|
||||||
async def resolve_package_dependencies(
|
async def resolve_package_dependencies(
|
||||||
package_name: str,
|
package_name: str,
|
||||||
python_version: Optional[str] = None,
|
python_version: str | None = None,
|
||||||
include_extras: Optional[List[str]] = None,
|
include_extras: list[str] | None = None,
|
||||||
include_dev: bool = False,
|
include_dev: bool = False,
|
||||||
max_depth: int = 5
|
max_depth: int = 5
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Resolve package dependencies with comprehensive analysis.
|
"""Resolve package dependencies with comprehensive analysis.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
"""Package download tools for PyPI packages."""
|
"""Package download tools for PyPI packages."""
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional, Set
|
from typing import Any
|
||||||
from urllib.parse import urlparse
|
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from ..core import PyPIClient, PyPIError
|
from ..core import PyPIClient, PyPIError
|
||||||
from ..core.exceptions import InvalidPackageNameError, NetworkError, PackageNotFoundError
|
from ..core.exceptions import (
|
||||||
|
InvalidPackageNameError,
|
||||||
|
NetworkError,
|
||||||
|
PackageNotFoundError,
|
||||||
|
)
|
||||||
from .dependency_resolver import DependencyResolver
|
from .dependency_resolver import DependencyResolver
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -28,13 +29,13 @@ class PackageDownloader:
|
|||||||
async def download_package_with_dependencies(
|
async def download_package_with_dependencies(
|
||||||
self,
|
self,
|
||||||
package_name: str,
|
package_name: str,
|
||||||
python_version: Optional[str] = None,
|
python_version: str | None = None,
|
||||||
include_extras: Optional[List[str]] = None,
|
include_extras: list[str] | None = None,
|
||||||
include_dev: bool = False,
|
include_dev: bool = False,
|
||||||
prefer_wheel: bool = True,
|
prefer_wheel: bool = True,
|
||||||
verify_checksums: bool = True,
|
verify_checksums: bool = True,
|
||||||
max_depth: int = 5
|
max_depth: int = 5
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Download a package and all its dependencies.
|
"""Download a package and all its dependencies.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -110,11 +111,11 @@ class PackageDownloader:
|
|||||||
async def _download_single_package(
|
async def _download_single_package(
|
||||||
self,
|
self,
|
||||||
package_name: str,
|
package_name: str,
|
||||||
version: Optional[str] = None,
|
version: str | None = None,
|
||||||
python_version: Optional[str] = None,
|
python_version: str | None = None,
|
||||||
prefer_wheel: bool = True,
|
prefer_wheel: bool = True,
|
||||||
verify_checksums: bool = True
|
verify_checksums: bool = True
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Download a single package."""
|
"""Download a single package."""
|
||||||
|
|
||||||
logger.info(f"Downloading {package_name} version {version or 'latest'}")
|
logger.info(f"Downloading {package_name} version {version or 'latest'}")
|
||||||
@ -157,10 +158,10 @@ class PackageDownloader:
|
|||||||
|
|
||||||
def _select_best_file(
|
def _select_best_file(
|
||||||
self,
|
self,
|
||||||
release_files: List[Dict[str, Any]],
|
release_files: list[dict[str, Any]],
|
||||||
python_version: Optional[str] = None,
|
python_version: str | None = None,
|
||||||
prefer_wheel: bool = True
|
prefer_wheel: bool = True
|
||||||
) -> Optional[Dict[str, Any]]:
|
) -> dict[str, Any] | None:
|
||||||
"""Select the best file to download from available release files."""
|
"""Select the best file to download from available release files."""
|
||||||
|
|
||||||
# Separate wheels and source distributions
|
# Separate wheels and source distributions
|
||||||
@ -187,9 +188,9 @@ class PackageDownloader:
|
|||||||
|
|
||||||
def _filter_compatible_wheels(
|
def _filter_compatible_wheels(
|
||||||
self,
|
self,
|
||||||
wheels: List[Dict[str, Any]],
|
wheels: list[dict[str, Any]],
|
||||||
python_version: str
|
python_version: str
|
||||||
) -> List[Dict[str, Any]]:
|
) -> list[dict[str, Any]]:
|
||||||
"""Filter wheels compatible with the specified Python version."""
|
"""Filter wheels compatible with the specified Python version."""
|
||||||
|
|
||||||
# Simple compatibility check based on filename
|
# Simple compatibility check based on filename
|
||||||
@ -213,9 +214,9 @@ class PackageDownloader:
|
|||||||
|
|
||||||
async def _download_file(
|
async def _download_file(
|
||||||
self,
|
self,
|
||||||
file_info: Dict[str, Any],
|
file_info: dict[str, Any],
|
||||||
verify_checksums: bool = True
|
verify_checksums: bool = True
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Download a single file."""
|
"""Download a single file."""
|
||||||
|
|
||||||
url = file_info.get("url")
|
url = file_info.get("url")
|
||||||
@ -269,9 +270,9 @@ class PackageDownloader:
|
|||||||
|
|
||||||
def _generate_download_summary(
|
def _generate_download_summary(
|
||||||
self,
|
self,
|
||||||
download_results: Dict[str, Any],
|
download_results: dict[str, Any],
|
||||||
failed_downloads: List[Dict[str, Any]]
|
failed_downloads: list[dict[str, Any]]
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Generate download summary statistics."""
|
"""Generate download summary statistics."""
|
||||||
|
|
||||||
successful_downloads = len(download_results)
|
successful_downloads = len(download_results)
|
||||||
@ -295,13 +296,13 @@ class PackageDownloader:
|
|||||||
async def download_package_with_dependencies(
|
async def download_package_with_dependencies(
|
||||||
package_name: str,
|
package_name: str,
|
||||||
download_dir: str = "./downloads",
|
download_dir: str = "./downloads",
|
||||||
python_version: Optional[str] = None,
|
python_version: str | None = None,
|
||||||
include_extras: Optional[List[str]] = None,
|
include_extras: list[str] | None = None,
|
||||||
include_dev: bool = False,
|
include_dev: bool = False,
|
||||||
prefer_wheel: bool = True,
|
prefer_wheel: bool = True,
|
||||||
verify_checksums: bool = True,
|
verify_checksums: bool = True,
|
||||||
max_depth: int = 5
|
max_depth: int = 5
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Download a package and its dependencies to local directory.
|
"""Download a package and its dependencies to local directory.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
"""Tests for dependency resolver functionality."""
|
"""Tests for dependency resolver functionality."""
|
||||||
|
|
||||||
import pytest
|
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from pypi_query_mcp.tools.dependency_resolver import DependencyResolver, resolve_package_dependencies
|
import pytest
|
||||||
|
|
||||||
from pypi_query_mcp.core.exceptions import InvalidPackageNameError, PackageNotFoundError
|
from pypi_query_mcp.core.exceptions import InvalidPackageNameError, PackageNotFoundError
|
||||||
|
from pypi_query_mcp.tools.dependency_resolver import (
|
||||||
|
DependencyResolver,
|
||||||
|
resolve_package_dependencies,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestDependencyResolver:
|
class TestDependencyResolver:
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
"""Tests for package downloader functionality."""
|
"""Tests for package downloader functionality."""
|
||||||
|
|
||||||
import pytest
|
|
||||||
from pathlib import Path
|
|
||||||
from unittest.mock import AsyncMock, patch, mock_open
|
|
||||||
import tempfile
|
|
||||||
import shutil
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
from unittest.mock import AsyncMock, mock_open, patch
|
||||||
|
|
||||||
from pypi_query_mcp.tools.package_downloader import PackageDownloader, download_package_with_dependencies
|
import pytest
|
||||||
from pypi_query_mcp.core.exceptions import InvalidPackageNameError, PackageNotFoundError
|
|
||||||
|
from pypi_query_mcp.core.exceptions import InvalidPackageNameError
|
||||||
|
from pypi_query_mcp.tools.package_downloader import (
|
||||||
|
PackageDownloader,
|
||||||
|
download_package_with_dependencies,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestPackageDownloader:
|
class TestPackageDownloader:
|
||||||
@ -218,25 +221,6 @@ class TestPackageDownloader:
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_download_package_with_dependencies_function(self, temp_download_dir):
|
async def test_download_package_with_dependencies_function(self, temp_download_dir):
|
||||||
"""Test the standalone download_package_with_dependencies function."""
|
"""Test the standalone download_package_with_dependencies function."""
|
||||||
mock_package_data = {
|
|
||||||
"info": {
|
|
||||||
"name": "test-package",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"requires_python": ">=3.8",
|
|
||||||
"requires_dist": []
|
|
||||||
},
|
|
||||||
"releases": {
|
|
||||||
"1.0.0": [
|
|
||||||
{
|
|
||||||
"filename": "test_package-1.0.0-py3-none-any.whl",
|
|
||||||
"url": "https://files.pythonhosted.org/packages/test_package-1.0.0-py3-none-any.whl",
|
|
||||||
"packagetype": "bdist_wheel",
|
|
||||||
"md5_digest": "abc123",
|
|
||||||
"size": 1024
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
with patch('pypi_query_mcp.tools.package_downloader.PackageDownloader') as mock_downloader_class:
|
with patch('pypi_query_mcp.tools.package_downloader.PackageDownloader') as mock_downloader_class:
|
||||||
# Setup downloader mock
|
# Setup downloader mock
|
||||||
|
Loading…
x
Reference in New Issue
Block a user