8000 fix: resolve all lint issues and fix failing tests · loonghao/pypi-query-mcp-server@a28d999 · GitHub
[go: up one dir, main page]

Skip to content

Commit a28d999

Browse files
committed
fix: resolve all lint issues and fix failing tests
- Fix blank line whitespace issues (W293) using ruff --unsafe-fixes - Reformat code using ruff format for consistent styling - Fix analyze_package_quality function to return list[Message] instead of string - Add missing 'assessment' keyword to package analysis template - Update tests to use real prompt functions instead of mocks for structure validation - Fix import ordering in test files - All 64 tests now pass with 47% code coverage Signed-off-by: longhao <hal.long@outlook.com>
1 parent d63ef02 commit a28d999

18 files changed

+554
-390
lines changed

examples/dependency_analysis_demo.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,21 @@ async def analyze_pyside2_dependencies():
2424
python_version="3.10",
2525
include_extras=[],
2626
include_dev=False,
27-
max_depth=3
27+
max_depth=3,
2828
)
2929

3030
print(f"✅ Successfully resolved dependencies for {result['package_name']}")
3131
print("📊 Summary:")
32-
summary = result['summary']
32+
summary = result["summary"]
3333
print(f" - Total packages: {summary['total_packages']}")
3434
print(f" - Runtime dependencies: {summary['total_runtime_dependencies']}")
3535
print(f" - Max depth: {summary['max_depth']}")
3636

3737
print("\n📦 Package list:")
38-
for i, pkg in enumerate(summary['package_list'][:10], 1): # Show first 10
38+
for i, pkg in enumerate(summary["package_list"][:10], 1): # Show first 10
3939
print(f" {i}. {pkg}")
4040

41-
if len(summary['package_list']) > 10:
41+
if len(summary["package_list"]) > 10:
4242
print(f" ... and {len(summary['package_list']) - 10} more packages")
4343

4444
return result
@@ -63,22 +63,22 @@ async def download_pyside2_packages():
6363
include_dev=False,
6464
prefer_wheel=True,
6565
verify_checksums=True,
66-
max_depth=2 # Limit depth for demo
66+
max_depth=2, # Limit depth for demo
6767
)
6868

6969
print("✅ Download completed!")
7070
print("📊 Download Summary:")
71-
summary = result['summary']
71+
summary = result["summary"]
7272
print(f" - Total packages: {summary['total_packages']}")
7373
print(f" - Successful downloads: {summary['successful_downloads']}")
7474
print(f" - Failed downloads: {summary['failed_downloads']}")
7575
print(f" - Total size: {summary['total_downloaded_size']:,} bytes")
7676
print(f" - Success rate: {summary['success_rate']:.1f}%")
7777
print(f" - Download directory: {summary['download_directory']}")
7878

79-
if result['failed_downloads']:
79+
if result["failed_downloads"]:
8080
print("\n⚠️ Failed downloads:")
81-
for failure in result['failed_downloads']:
81+
for failure in result["failed_downloads"]:
8282
print(f" - {failure['package']}: {failure['error']}")
8383

8484
return result
@@ -98,20 +98,20 @@ async def analyze_small_package():
9898
python_version="3.10",
9999
include_extras=[],
100100
include_dev=False,
101-
max_depth=5
101+
max_depth=5,
102102
)
103103

104104
print(f"✅ Successfully resolved dependencies for {result['package_name']}")
105105

106106
# Show detailed dependency tree
107107
print("\n🌳 Dependency Tree:")
108-
dependency_tree = result['dependency_tree']
108+
dependency_tree = result["dependency_tree"]
109109

110110
for _pkg_name, pkg_info in dependency_tree.items():
111-
indent = " " * pkg_info['depth']
111+
indent = " " * pkg_info["depth"]
112112
print(f"{indent}- {pkg_info['name']} ({pkg_info['version']})")
113113

114-
runtime_deps = pkg_info['dependencies']['runtime']
114+
runtime_deps = pkg_info["dependencies"]["runtime"]
115115
if runtime_deps:
116116
for dep in runtime_deps[:3]: # Show first 3 dependencies
117117
print(f"{indent} └─ {dep}")

examples/download_stats_demo.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ async def demo_package_download_stats():
5454
print(f" Total Downloads: {analysis.get('total_downloads', 0):,}")
5555
print(f" Highest Period: {analysis.get('highest_period', 'N/A')}")
5656

57-
growth = analysis.get('growth_indicators', {})
57+
growth = analysis.get("growth_indicators", {})
5858
if growth:
5959
print(" Growth Indicators:")
6060
for indicator, value in growth.items():
6161
print(f" {indicator}: {value}")
6262

6363
# Display repository info if available
64-
project_urls = metadata.get('project_urls', {})
64+
project_urls = metadata.get("project_urls", {})
6565
if project_urls:
6666
print("\nRepository Links:")
6767
for name, url in project_urls.items():
@@ -98,22 +98,28 @@ async def demo_package_download_trends():
9898
print(f"Trend Direction: {trend_analysis.get('trend_direction', 'unknown')}")
9999

100100
# Display date range
101-
date_range = trend_analysis.get('date_range', {})
101+
date_range = trend_analysis.get("date_range", {})
102102
if date_range:
103103
print(f"Date Range: {date_range.get('start')} to {date_range.get('end')}")
104104

105105
# Display peak day
106-
peak_day = trend_analysis.get('peak_day', {})
106+
peak_day = trend_analysis.get("peak_day", {})
107107
if peak_day:
108-
print(f"Peak Day: {peak_day.get('date')} ({peak_day.get('downloads', 0):,} downloads)")
108+
print(
109+
f"Peak Day: {peak_day.get('date')} ({peak_day.get('downloads', 0):,} downloads)"
110+
)
109111

110112
# Show recent data points (last 7 days)
111113
if time_series:
112114
print("\nRecent Download Data (last 7 days):")
113-
recent_data = [item for item in time_series if item.get('category') == 'without_mirrors'][-7:]
115+
recent_data = [
116+
item
117+
for item in time_series
118+
if item.get("category") == "without_mirrors"
119+
][-7:]
114120
for item in recent_data:
115-
date = item.get('date', 'unknown')
116-
downloads = item.get('downloads', 0)
121+
date = item.get("date", "unknown")
122+
downloads = item.get("downloads", 0)
117123
print(f" {date}: {downloads:,} downloads")
118124

119125
except Exception as e:
@@ -176,11 +182,13 @@ async def demo_package_comparison():
176182
downloads = stats.get("downloads", {})
177183
last_month = downloads.get("last_month", 0)
178184

179-
comparison_data.append({
180-
"name": framework,
181-
"downloads": last_month,
182-
"metadata": stats.get("metadata", {}),
183-
})
185+
comparison_data.append(
186+
{
187+
"name": framework,
188+
"downloads": last_month,
189+
"metadata": stats.get("metadata", {}),
190+
}
191+
)
184192

185193
except Exception as e:
186194
print(f"❌ Error getting stats for {framework}: {e}")

examples/prompt_templates_demo.py

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ async def demo_package_analysis_prompts():
3434
print("-" * 30)
3535

3636
result = await client.get_prompt(
37-
"analyze_package_quality",
38-
{"package_name": "requests", "version": "2.31.0"}
37+
"analyze_package_quality", {"package_name": "requests", "version": "2.31.0"}
3938
)
4039

4140
print("Prompt generated for analyzing 'requests' package quality:")
@@ -50,8 +49,8 @@ async def demo_package_analysis_prompts():
5049
{
5150
"packages": ["requests", "httpx", "aiohttp"],
5251
"use_case": "Building a high-performance web API client",
53-
"criteria": ["performance", "async support", "ease of use"]
54-
}
52+
"criteria": ["performance", "async support", "ease of use"],
53+
},
5554
)
5655

5756
print("Prompt generated for comparing HTTP client libraries:")
@@ -66,8 +65,8 @@ async def demo_package_analysis_prompts():
6665
{
6766
"package_name": "flask",
6867
"reason": "performance",
69-
"requirements": "Need async support and better performance for high-traffic API"
70-
}
68+
"requirements": "Need async support and better performance for high-traffic API",
69+
},
7170
)
7271

7372
print("Prompt generated for finding Flask alternatives:")
@@ -91,11 +90,11 @@ async def demo_dependency_management_prompts():
9190
{
9291
"conflicts": [
9392
"django 4.2.0 requires sqlparse>=0.3.1, but you have sqlparse 0.2.4",
94-
"Package A requires numpy>=1.20.0, but Package B requires numpy<1.19.0"
93+
"Package A requires numpy>=1.20.0, but Package B requires numpy<1.19.0",
9594
],
9695
"python_version": "3.10",
97-
"project_context": "Django web application with data analysis features"
98-
}
96+
"project_context": "Django web application with data analysis features",
97+
},
9998
)
10099

101100
print("Prompt generated for resolving dependency conflicts:")
@@ -111,8 +110,8 @@ async def demo_dependency_management_prompts():
111110
"package_name": "django",
112111
"current_version": "3.2.0",
113112
"target_version": "4.2.0",
114-
"project_size": "large"
115-
}
113+
"project_size": "large",
114+
},
116115
)
117116

118117
print("Prompt generated for Django upgrade planning:")
@@ -127,8 +126,8 @@ async def demo_dependency_management_prompts():
127126
{
128127
"packages": ["django", "requests", "pillow", "cryptography"],
129128
"environment": "production",
130-
"compliance_requirements": "SOC2, GDPR compliance required"
131-
}
129+
"compliance_requirements": "SOC2, GDPR compliance required",
130+
},
132131
)
133132

134133
print("Prompt generated for security audit:")
@@ -154,8 +153,8 @@ async def demo_migration_prompts():
154153
"to_package": "fastapi",
155154
"codebase_size": "medium",
156155
"timeline": "2 months",
157-
"team_size": 4
158-
}
156+
"team_size": 4,
157+
},
159158
)
160159

161160
print("Prompt generated for Flask to FastAPI migration:")
@@ -170,8 +169,8 @@ async def demo_migration_prompts():
170169
{
171170
"migration_type": "package_replacement",
172171
"packages_involved": ["flask", "fastapi", "pydantic"],
173-
"environment": "production"
174-
}
172+
"environment": "production",
173+
},
175174
)
176175

177176
print("Prompt generated for migration checklist:")
@@ -197,7 +196,9 @@ async def demo_prompt_list():
197196
print(" Arguments:")
198197
for arg in prompt.arguments:
199198
required = " (required)" if arg.required else " (optional)"
200-
print(f" - {arg.name}{required}: {arg.description or 'No description'}")
199+
print(
200+
f" - {arg.name}{required}: {arg.description or 'No description'}"
201+
)
201202

202203

203204
async def main():
@@ -225,7 +226,9 @@ async def main():
225226

226227
except Exception as e:
227228
print(f"\n❌ Error running demo: {e}")
228-
print("\nMake sure the PyPI Query MCP Server is properly installed and configured.")
229+
print(
230+
"\nMake sure the PyPI Query MCP Server is properly installed and configured."
231+
)
229232

230233

231234
if __name__ == "__main__":

pypi_query_mcp/core/dependency_parser.py

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ def parse_requirements(self, requires_dist: list[str]) -> list[Requirement]:
4141
return requirements
4242

4343
def filter_requirements_by_python_version(
44-
self,
45-
requirements: list[Requirement],
46-
python_version: str
44+
self, requirements: list[Requirement], python_version: str
4745
) -> list[Requirement]:
4846
"""Filter requirements based on Python version.
4947
@@ -68,7 +66,9 @@ def filter_requirements_by_python_version(
6866

6967
return filtered
7068

71-
def _is_requirement_applicable(self, req: Requirement, python_version: Version) -> bool:
69+
def _is_requirement_applicable(
70+
self, req: Requirement, python_version: Version
71+
) -> bool:
7272
"""Check if a requirement is applicable for the given Python version.
7373
7474
Args:
@@ -83,12 +83,12 @@ def _is_requirement_applicable(self, req: Requirement, python_version: Version)
8383

8484
# Create environment for marker evaluation
8585
env = {
86-
'python_version': str(python_version),
87-
'python_full_version': str(python_version),
88-
'platform_system': 'Linux', # Default assumption
89-
'platform_machine': 'x86_64', # Default assumption
90-
'implementation_name': 'cpython',
91-
'implementation_version': str(python_version),
86+
"python_version": str(python_version),
87+
"python_full_version": str(python_version),
88+
"platform_system": "Linux", # Default assumption
89+
"platform_machine": "x86_64", # Default assumption
90+
"implementation_name": "cpython",
91+
"implementation_version": str(python_version),
9292
}
9393

9494
try:
@@ -98,8 +98,7 @@ def _is_requirement_applicable(self, req: Requirement, python_version: Version)
9898
return True # Include by default if evaluation fails
9999

100100
def categorize_dependencies(
101-
self,
102-
requirements: list[Requirement]
101+
self, requirements: list[Requirement]
103102
) -> dict[str, list[Requirement]]:
104103
"""Categorize dependencies into runtime, development, and optional groups.
105104
@@ -109,36 +108,34 @@ def categorize_dependencies(
109108
Returns:
110109
Dictionary with categorized dependencies
111110
"""
112-
categories = {
113-
'runtime': [],
114-
'development': [],
115-
'optional': {},
116-
'extras': {}
117-
}
111+
categories = {"runtime": [], "development": [], "optional": {}, "extras": {}}
118112

119113
for req in requirements:
120114
if not req.marker:
121115
# No marker means it's a runtime dependency
122-
categories['runtime'].append(req)
116+
categories["runtime"].append(req)
123117
continue
124118

125119
marker_str = str(req.marker)
126120

127121
# Check for extra dependencies
128-
if 'extra ==' in marker_str:
122+
if "extra ==" in marker_str:
129123
extra_match = re.search(r'extra\s*==\s*["\']([^"\']+)["\']', marker_str)
130124
if extra_match:
131125
extra_name = extra_match.group(1)
132-
if extra_name not in categories['extras']:
133-
categories['extras'][extra_name] = []
134-
categories['extras'][extra_name].append(req)
126+
if extra_name not in categories["extras"]:
127+
categories["extras"][extra_name] = []
128+
categories["extras"][extra_name].append(req)
135129
continue
136130

137131
# Check for development dependencies
138-
if any(keyword in marker_str.lower() for keyword in ['dev', 'test', 'lint', 'doc']):
139-
categories['development'].append(req)
132+
if any(
133+
keyword in marker_str.lower()
134+
for keyword in ["dev", "test", "lint", "doc"]
135+
):
136+
categories["development"].append(req)
140137
else:
141-
categories['runtime'].append(req)
138+
categories["runtime"].append(req)
142139

143140
return categories
144141

@@ -163,17 +160,16 @@ def get_version_constraints(self, req: Requirement) -> dict[str, Any]:
163160
Dictionary with version constraint information
164161
"""
165162
if not req.specifier:
166-
return {'constraints': [], 'allows_any': True}
163+
return {"constraints": [], "allows_any": True}
167164

168165
constraints = []
169166
for spec in req.specifier:
170-
constraints.append({
171-
'operator': spec.operator,
172-
'version': str(spec.version)
173-
})
167+
constraints.append(
168+
{"operator": spec.operator, "version": str(spec.version)}
169+
)
174170

175171
return {
176-
'constraints': constraints,
177-
'allows_any': len(constraints) == 0,
178-
'specifier_str': str(req.specifier)
172+
"constraints": constraints,
173+
"allows_any": len(constraints) == 0,
174+
"specifier_str": str(req.specifier),
179175
}

0 commit comments

Comments
 (0)
0