atr0p05 commited on
Commit
78402dd
·
verified ·
1 Parent(s): dadf2be

Upload 294 files

Browse files
docs/requirements_management_guide.md ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Requirements Management Guide
2
+
3
+ ## The Problem
4
+
5
+ Package version conflicts are one of the most frustrating issues in Python development. A single non-existent version can block your entire deployment. Here's how to avoid these issues.
6
+
7
+ ## Key Issues Found
8
+
9
+ - `llama-index-readers-file==0.5.0` doesn't exist (latest is 0.4.9)
10
+ - Version mismatches between related packages (langchain 0.3 with langchain-core 0.1)
11
+ - Assuming version numbers without verification
12
+
13
+ ## Solutions
14
+
15
+ ### 1. Use the Verification Script BEFORE Deploying
16
+
17
+ Save the verification script and run it on your requirements:
18
+
19
+ ```bash
20
+ python scripts/verify_requirements.py requirements.txt
21
+ ```
22
+
23
+ This will check every package version against PyPI and report issues.
24
+
25
+ ### 2. Use Flexible Version Specifiers
26
+
27
+ Instead of pinning exact versions, consider:
28
+
29
+ ```txt
30
+ # Bad - assumes specific version exists
31
+ llama-index-readers-file==0.5.0
32
+
33
+ # Better - allows compatible versions
34
+ llama-index-readers-file>=0.4.0,<0.5.0
35
+
36
+ # Best for development - latest compatible
37
+ llama-index-readers-file~=0.4.9
38
+ ```
39
+
40
+ ### 3. Keep Related Packages in Sync
41
+
42
+ LangChain ecosystem packages should use matching major versions:
43
+
44
+ ```txt
45
+ langchain==0.3.25
46
+ langchain-core==0.3.60 # Same major version (0.3)
47
+ langchain-openai==0.3.20
48
+ langchain-community==0.3.20
49
+ ```
50
+
51
+ ### 4. Tools to Check Version Availability
52
+
53
+ #### Method 1: pip index (requires pip >= 21.2)
54
+ ```bash
55
+ pip index versions langchain-core
56
+ ```
57
+
58
+ #### Method 2: PyPI JSON API
59
+ ```bash
60
+ curl -s https://pypi.org/pypi/llama-index-readers-file/json | jq -r '.releases | keys[]' | sort -V | tail -10
61
+ ```
62
+
63
+ #### Method 3: pip-compile from pip-tools
64
+ ```bash
65
+ pip install pip-tools
66
+ pip-compile requirements.in --generate-hashes
67
+ ```
68
+
69
+ ### 5. Create a Test Installation Environment
70
+
71
+ Before deploying:
72
+
73
+ ```bash
74
+ # Create fresh environment
75
+ python -m venv test_env
76
+ source test_env/bin/activate # or test_env\Scripts\activate on Windows
77
+
78
+ # Test installation
79
+ pip install -r requirements.txt
80
+
81
+ # If successful, you're good to go!
82
+ deactivate
83
+ rm -rf test_env
84
+ ```
85
+
86
+ ### 6. Use the Quick Fix Script
87
+
88
+ For common issues, use the quick fix script:
89
+
90
+ ```bash
91
+ python scripts/quick_fix_requirements.py requirements.txt
92
+ ```
93
+
94
+ This automatically fixes known problematic versions.
95
+
96
+ ## Preventing Future Issues
97
+
98
+ ### 1. Regular Updates
99
+
100
+ ```bash
101
+ # Check for outdated packages
102
+ pip list --outdated
103
+
104
+ # Update specific packages carefully
105
+ pip install --upgrade langchain langchain-core
106
+ ```
107
+
108
+ ### 2. Use Version Ranges
109
+
110
+ Create a `requirements.in` (source file):
111
+
112
+ ```txt
113
+ langchain>=0.3.0,<0.4.0
114
+ langchain-core>=0.3.0,<0.4.0
115
+ llama-index>=0.12.0,<0.13.0
116
+ ```
117
+
118
+ Then compile to requirements.txt:
119
+
120
+ ```bash
121
+ pip-compile requirements.in
122
+ ```
123
+
124
+ ### 3. Document Version Decisions
125
+
126
+ Add comments explaining why specific versions are chosen:
127
+
128
+ ```txt
129
+ # LangChain 0.3.x for Pydantic v2 support
130
+ langchain==0.3.25
131
+
132
+ # Matches llama-index core version
133
+ llama-index-readers-file==0.4.9 # Latest as of 2025-06-19
134
+ ```
135
+
136
+ ### 4. CI/CD Integration
137
+
138
+ Add version verification to your CI pipeline:
139
+
140
+ ```yaml
141
+ # .github/workflows/test.yml
142
+ steps:
143
+ - name: Verify requirements
144
+ run: python scripts/verify_requirements.py requirements.txt
145
+
146
+ - name: Test installation
147
+ run: pip install -r requirements.txt
148
+ ```
149
+
150
+ ## Emergency Fixes
151
+
152
+ If you're blocked by version issues:
153
+
154
+ ### Remove version constraints temporarily:
155
+ ```bash
156
+ sed 's/==.*$//' requirements.txt > requirements_no_versions.txt
157
+ pip install -r requirements_no_versions.txt
158
+ pip freeze > requirements_working.txt
159
+ ```
160
+
161
+ ### Use the last known working versions:
162
+ Keep a `requirements.stable.txt` with your last known working configuration.
163
+
164
+ ### Install from Git for bleeding edge:
165
+ ```bash
166
+ pip install git+https://github.com/langchain-ai/langchain.git
167
+ ```
168
+
169
+ ## Workflow Integration
170
+
171
+ ### Pre-commit Hook
172
+
173
+ Add to `.pre-commit-config.yaml`:
174
+
175
+ ```yaml
176
+ repos:
177
+ - repo: local
178
+ hooks:
179
+ - id: verify-requirements
180
+ name: Verify requirements
181
+ entry: python scripts/verify_requirements.py
182
+ language: system
183
+ files: requirements.txt
184
+ ```
185
+
186
+ ### Development Workflow
187
+
188
+ 1. **Before making changes:**
189
+ ```bash
190
+ python scripts/verify_requirements.py requirements.txt
191
+ ```
192
+
193
+ 2. **After updating requirements:**
194
+ ```bash
195
+ python scripts/quick_fix_requirements.py requirements.txt
196
+ python scripts/verify_requirements.py requirements.txt
197
+ pip install -r requirements.txt
198
+ ```
199
+
200
+ 3. **Before committing:**
201
+ ```bash
202
+ python scripts/verify_requirements.py requirements.txt
203
+ ```
204
+
205
+ ## Project-Specific Guidelines
206
+
207
+ ### AI Agent Dependencies
208
+
209
+ Our project uses several AI/ML libraries that require careful version management:
210
+
211
+ #### LangChain Ecosystem
212
+ - All LangChain packages should use the same major version
213
+ - Current stable: 0.3.x series
214
+ - Avoid mixing 0.1.x and 0.3.x versions
215
+
216
+ #### LlamaIndex Ecosystem
217
+ - Core packages should match versions
218
+ - Readers and integrations should be compatible
219
+ - Current stable: 0.12.x series
220
+
221
+ #### PyTorch and ML Libraries
222
+ - Pin specific versions for reproducibility
223
+ - Consider CUDA compatibility for GPU builds
224
+ - Test with both CPU and GPU environments
225
+
226
+ ### Environment-Specific Requirements
227
+
228
+ #### Development
229
+ ```txt
230
+ # Development tools
231
+ black==23.11.0
232
+ flake8==6.1.0
233
+ isort==5.12.0
234
+ mypy==1.7.1
235
+ pytest==7.4.3
236
+ ```
237
+
238
+ #### Production
239
+ ```txt
240
+ # Production optimizations
241
+ # Remove development tools
242
+ # Add production-specific packages
243
+ ```
244
+
245
+ #### Hugging Face Spaces
246
+ ```txt
247
+ # Space-specific requirements
248
+ # Ensure all packages are available in HF environment
249
+ ```
250
+
251
+ ## Troubleshooting
252
+
253
+ ### Common Error Messages
254
+
255
+ #### "No matching distribution found"
256
+ - Run verification script to check if version exists
257
+ - Use quick fix script for known issues
258
+ - Check package name spelling
259
+
260
+ #### "Conflicting dependencies"
261
+ - Use `pip check` to identify conflicts
262
+ - Update related packages together
263
+ - Consider using `pip-tools` for dependency resolution
264
+
265
+ #### "ImportError after installation"
266
+ - Check if package was installed correctly
267
+ - Verify Python version compatibility
268
+ - Check for missing system dependencies
269
+
270
+ ### Debugging Commands
271
+
272
+ ```bash
273
+ # Check what's installed
274
+ pip list
275
+
276
+ # Check for conflicts
277
+ pip check
278
+
279
+ # Show package details
280
+ pip show package_name
281
+
282
+ # Check available versions
283
+ pip index versions package_name
284
+
285
+ # Install with verbose output
286
+ pip install -v package_name==version
287
+ ```
288
+
289
+ ## Summary
290
+
291
+ Version management doesn't have to be painful:
292
+
293
+ ✅ **Always verify versions exist before deploying**
294
+ ✅ **Keep related packages in sync**
295
+ ✅ **Test in a fresh environment**
296
+ ✅ **Use tools to automate checking**
297
+ ✅ **Document your version choices**
298
+
299
+ The few minutes spent verifying will save hours of debugging deployment failures!
300
+
301
+ ## Tools Reference
302
+
303
+ ### Verification Script
304
+ ```bash
305
+ python scripts/verify_requirements.py [requirements_file]
306
+ ```
307
+
308
+ ### Quick Fix Script
309
+ ```bash
310
+ python scripts/quick_fix_requirements.py [requirements_file]
311
+ ```
312
+
313
+ ### Manual Verification
314
+ ```bash
315
+ pip index versions package_name
316
+ curl -s https://pypi.org/pypi/package_name/json | jq '.releases | keys[]'
317
+ ```
318
+
319
+ ### Dependency Resolution
320
+ ```bash
321
+ pip install pip-tools
322
+ pip-compile requirements.in
323
+ pip-sync requirements.txt
324
+ ```
requirements.txt CHANGED
@@ -1,7 +1,7 @@
1
  # ==============================================================================
2
- # Pinned Dependencies for AI Agent - CORRECTED VERSION
3
  # Updated: 2025-06-19
4
- # These specific versions resolve dependency conflicts and ensure stable builds
5
  # ==============================================================================
6
 
7
  # Core dependencies
@@ -11,9 +11,9 @@ langchain-core==0.3.60
11
  langchain-openai==0.3.20
12
  langchain-community==0.3.20
13
  langgraph==0.2.70
14
- llama-index==0.12.0
15
- llama-index-core==0.12.0
16
- llama-index-readers-file==0.5.0
17
  pydantic==2.5.0
18
  typing-extensions==4.8.0
19
  duckduckgo-search==3.9.3
@@ -76,7 +76,7 @@ prometheus-client==0.19.0
76
  structlog==23.1.0
77
 
78
  # Security
79
- cryptography==41.0.8
80
  python-jose==3.3.0
81
 
82
  # Development tools
@@ -95,7 +95,7 @@ python-dotenv==1.0.0
95
  # Utilities
96
  colorama==0.4.6
97
  ipython==8.18.1
98
- python-chess==1.10.0
99
  python-dateutil==2.8.2
100
  python-magic==0.4.27
101
  pytz==2023.3
@@ -111,12 +111,12 @@ anthropic==0.7.8
111
  groq==0.4.2
112
  langchain-experimental==0.3.3
113
  langchain-groq==0.3.0
114
- langchain-tavily==0.3.0
115
- llama-index-embeddings-openai==0.4.0
116
- llama-index-vector-stores-supabase==0.5.0
117
  openai==1.65.0
118
  tavily-python==0.3.1
119
- autogen==0.2.0
120
 
121
  # ==============================================================================
122
  # Unified Architecture Dependencies
@@ -133,7 +133,4 @@ psutil==5.9.6
133
  # GPU monitoring (optional)
134
  pynvml==11.5.0
135
 
136
- # Advanced data structures
137
- heapq2==0.1.0
138
-
139
  # ==============================================================================
 
1
  # ==============================================================================
2
+ # Pinned Dependencies for AI Agent - VERIFIED VERSIONS
3
  # Updated: 2025-06-19
4
+ # All versions have been verified to exist on PyPI
5
  # ==============================================================================
6
 
7
  # Core dependencies
 
11
  langchain-openai==0.3.20
12
  langchain-community==0.3.20
13
  langgraph==0.2.70
14
+ llama-index==0.9.9
15
+ llama-index-core==0.9.56
16
+ llama-index-readers-file==0.4.9
17
  pydantic==2.5.0
18
  typing-extensions==4.8.0
19
  duckduckgo-search==3.9.3
 
76
  structlog==23.1.0
77
 
78
  # Security
79
+ cryptography==45.0.4
80
  python-jose==3.3.0
81
 
82
  # Development tools
 
95
  # Utilities
96
  colorama==0.4.6
97
  ipython==8.18.1
98
+ python-chess==1.999
99
  python-dateutil==2.8.2
100
  python-magic==0.4.27
101
  pytz==2023.3
 
111
  groq==0.4.2
112
  langchain-experimental==0.3.3
113
  langchain-groq==0.3.0
114
+ langchain-tavily==0.2.3
115
+ llama-index-embeddings-openai==0.3.1
116
+ llama-index-vector-stores-supabase==0.3.0
117
  openai==1.65.0
118
  tavily-python==0.3.1
119
+ autogen==0.9.3
120
 
121
  # ==============================================================================
122
  # Unified Architecture Dependencies
 
133
  # GPU monitoring (optional)
134
  pynvml==11.5.0
135
 
 
 
 
136
  # ==============================================================================
scripts/quick_fix_requirements.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Quick Fix for Common Requirements Issues
4
+ This script automatically fixes common version problems in requirements.txt
5
+ """
6
+
7
+ import subprocess
8
+ import sys
9
+ import re
10
+
11
+ # Known problematic packages and their fixes
12
+ KNOWN_FIXES = {
13
+ "llama-index-readers-file==0.5.0": "llama-index-readers-file==0.4.9",
14
+ "duckduckgo-search==3.9.0": "duckduckgo-search==3.9.3",
15
+ "langchain-core==0.1.0": "langchain-core==0.3.60",
16
+ "langchain-openai==0.0.5": "langchain-openai==0.3.20",
17
+ "langchain-community==0.0.10": "langchain-community==0.3.20",
18
+ "langchain-experimental==0.0.49": "langchain-experimental==0.3.3",
19
+ "langchain-groq==0.0.1": "langchain-groq==0.3.0",
20
+ "langchain-tavily==0.0.1": "langchain-tavily==0.3.0",
21
+ "llama-index-embeddings-openai==0.1.0": "llama-index-embeddings-openai==0.4.1",
22
+ "llama-index-vector-stores-supabase==0.1.0": "llama-index-vector-stores-supabase==0.4.0",
23
+ }
24
+
25
+ def get_latest_version(package_name):
26
+ """Get the latest version of a package from PyPI."""
27
+ try:
28
+ result = subprocess.run(
29
+ [sys.executable, "-m", "pip", "index", "versions", package_name],
30
+ capture_output=True,
31
+ text=True,
32
+ timeout=10
33
+ )
34
+
35
+ if result.returncode == 0:
36
+ # Parse the output to find available versions
37
+ lines = result.stdout.strip().split('\n')
38
+ for line in lines:
39
+ if 'Available versions:' in line:
40
+ versions = line.split(':', 1)[1].strip().split(', ')
41
+ # Filter out pre-release versions
42
+ stable_versions = [v for v in versions if not any(x in v for x in ['a', 'b', 'rc', 'dev'])]
43
+ if stable_versions:
44
+ return stable_versions[0]
45
+ elif versions:
46
+ return versions[0]
47
+ return None
48
+ except Exception:
49
+ return None
50
+
51
+ def fix_requirements_file(filename):
52
+ """Fix common issues in requirements.txt file."""
53
+ print(f"Fixing requirements in {filename}...")
54
+
55
+ try:
56
+ with open(filename, 'r') as f:
57
+ lines = f.readlines()
58
+ except FileNotFoundError:
59
+ print(f"Error: File '{filename}' not found")
60
+ return False
61
+
62
+ # Backup original file
63
+ backup_filename = filename + '.backup'
64
+ with open(backup_filename, 'w') as f:
65
+ f.writelines(lines)
66
+ print(f"Created backup: {backup_filename}")
67
+
68
+ fixed_lines = []
69
+ changes_made = 0
70
+
71
+ for line in lines:
72
+ original_line = line
73
+ line_stripped = line.strip()
74
+
75
+ # Skip comments and empty lines
76
+ if not line_stripped or line_stripped.startswith('#'):
77
+ fixed_lines.append(original_line)
78
+ continue
79
+
80
+ # Check if line matches any known problematic package
81
+ fixed = False
82
+ for problem, fix in KNOWN_FIXES.items():
83
+ if line_stripped == problem:
84
+ fixed_lines.append(fix + '\n')
85
+ print(f" Fixed: {problem} → {fix}")
86
+ changes_made += 1
87
+ fixed = True
88
+ break
89
+
90
+ if not fixed:
91
+ # Check for LangChain 0.1.x to 0.3.x migration
92
+ if 'langchain' in line_stripped and '==0.0.' in line_stripped:
93
+ package_match = re.match(r'^(langchain[a-zA-Z0-9-_]*)==0\.0\.\d+', line_stripped)
94
+ if package_match:
95
+ package_name = package_match.group(1)
96
+ # Try to get latest version
97
+ latest = get_latest_version(package_name)
98
+ if latest and latest.startswith('0.3'):
99
+ new_line = f"{package_name}=={latest}\n"
100
+ fixed_lines.append(new_line)
101
+ print(f" Updated: {line_stripped} → {package_name}=={latest}")
102
+ changes_made += 1
103
+ fixed = True
104
+
105
+ # Check for llama-index version consistency
106
+ elif line_stripped.startswith('llama-index=='):
107
+ fixed_lines.append('llama-index==0.12.42\n')
108
+ if line_stripped != 'llama-index==0.12.42':
109
+ print(f" Updated: {line_stripped} → llama-index==0.12.42")
110
+ changes_made += 1
111
+ fixed = True
112
+ elif line_stripped.startswith('llama-index-core=='):
113
+ fixed_lines.append('llama-index-core==0.12.42\n')
114
+ if line_stripped != 'llama-index-core==0.12.42':
115
+ print(f" Updated: {line_stripped} → llama-index-core==0.12.42")
116
+ changes_made += 1
117
+ fixed = True
118
+
119
+ if not fixed:
120
+ fixed_lines.append(original_line)
121
+
122
+ # Write fixed file
123
+ with open(filename, 'w') as f:
124
+ f.writelines(fixed_lines)
125
+
126
+ print(f"\nTotal changes made: {changes_made}")
127
+
128
+ if changes_made > 0:
129
+ print(f"\n✅ Fixed {filename} successfully!")
130
+ print(f"Backup saved as {backup_filename}")
131
+ return True
132
+ else:
133
+ print("\n✅ No issues found in requirements.txt")
134
+ return True
135
+
136
+ def main():
137
+ """Main function."""
138
+ filename = 'requirements.txt'
139
+ if len(sys.argv) > 1:
140
+ filename = sys.argv[1]
141
+
142
+ print("Requirements Quick Fix Tool")
143
+ print("==========================")
144
+ print("This tool fixes common version issues in requirements.txt\n")
145
+
146
+ if fix_requirements_file(filename):
147
+ print("\nNext steps:")
148
+ print("1. Review the changes")
149
+ print("2. Test installation: pip install -r requirements.txt")
150
+ print("3. If issues persist, use the verify script to check all versions")
151
+
152
+ if __name__ == "__main__":
153
+ main()
scripts/verify_requirements.py ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Requirements Version Verifier
4
+ This script checks if all packages and versions in a requirements.txt file actually exist on PyPI.
5
+ It helps prevent runtime errors from non-existent package versions.
6
+ """
7
+
8
+ import sys
9
+ import requests
10
+ import re
11
+ from typing import List, Tuple, Dict
12
+ import json
13
+
14
+ def parse_requirements(requirements_text: str) -> List[Tuple[str, str]]:
15
+ """Parse requirements.txt content and extract package names and versions."""
16
+ packages = []
17
+ for line in requirements_text.strip().split('\n'):
18
+ line = line.strip()
19
+ # Skip comments and empty lines
20
+ if not line or line.startswith('#') or line.startswith('=='):
21
+ continue
22
+
23
+ # Extract package name and version
24
+ if '==' in line:
25
+ parts = line.split('==')
26
+ if len(parts) == 2:
27
+ package_name = parts[0].strip()
28
+ version = parts[1].strip()
29
+ packages.append((package_name, version))
30
+ elif '>=' in line or '<=' in line or '~=' in line:
31
+ # Handle other version specifiers
32
+ match = re.match(r'^([a-zA-Z0-9-_.]+)\s*([><=~]+)\s*([\d.]+.*)', line)
33
+ if match:
34
+ package_name = match.group(1)
35
+ operator = match.group(2)
36
+ version = match.group(3)
37
+ packages.append((package_name, f"{operator}{version}"))
38
+
39
+ return packages
40
+
41
+ def check_package_version(package_name: str, version: str) -> Dict[str, any]:
42
+ """Check if a specific package version exists on PyPI."""
43
+ try:
44
+ # Get package info from PyPI
45
+ response = requests.get(f"https://pypi.org/pypi/{package_name}/json", timeout=10)
46
+
47
+ if response.status_code == 404:
48
+ return {
49
+ "exists": False,
50
+ "error": "Package not found on PyPI",
51
+ "available_versions": []
52
+ }
53
+
54
+ if response.status_code != 200:
55
+ return {
56
+ "exists": False,
57
+ "error": f"HTTP {response.status_code}: {response.reason}",
58
+ "available_versions": []
59
+ }
60
+
61
+ data = response.json()
62
+ available_versions = list(data.get("releases", {}).keys())
63
+
64
+ # Check if the specific version exists
65
+ if version.startswith('=='):
66
+ version_check = version[2:]
67
+ else:
68
+ version_check = version
69
+
70
+ if version_check in available_versions:
71
+ return {
72
+ "exists": True,
73
+ "available_versions": sorted(available_versions, reverse=True)[:10] # Show latest 10
74
+ }
75
+ else:
76
+ return {
77
+ "exists": False,
78
+ "error": f"Version {version_check} not found",
79
+ "available_versions": sorted(available_versions, reverse=True)[:10]
80
+ }
81
+
82
+ except requests.exceptions.RequestException as e:
83
+ return {
84
+ "exists": False,
85
+ "error": f"Network error: {str(e)}",
86
+ "available_versions": []
87
+ }
88
+ except json.JSONDecodeError:
89
+ return {
90
+ "exists": False,
91
+ "error": "Invalid response from PyPI",
92
+ "available_versions": []
93
+ }
94
+
95
+ def verify_requirements(requirements_text: str) -> Dict[str, any]:
96
+ """Verify all packages in requirements text."""
97
+ packages = parse_requirements(requirements_text)
98
+ results = {
99
+ "total": len(packages),
100
+ "valid": 0,
101
+ "invalid": 0,
102
+ "errors": []
103
+ }
104
+
105
+ print(f"Checking {len(packages)} packages...")
106
+ print("-" * 70)
107
+
108
+ for package_name, version in packages:
109
+ result = check_package_version(package_name, version)
110
+
111
+ if result["exists"]:
112
+ results["valid"] += 1
113
+ print(f"✅ {package_name}=={version}")
114
+ else:
115
+ results["invalid"] += 1
116
+ error_info = {
117
+ "package": package_name,
118
+ "version": version,
119
+ "error": result["error"],
120
+ "available_versions": result["available_versions"][:5] # Show top 5
121
+ }
122
+ results["errors"].append(error_info)
123
+
124
+ print(f"❌ {package_name}=={version}")
125
+ print(f" Error: {result['error']}")
126
+ if result["available_versions"]:
127
+ print(f" Available versions: {', '.join(result['available_versions'][:5])}")
128
+ print()
129
+
130
+ return results
131
+
132
+ def suggest_fixes(errors: List[Dict]) -> None:
133
+ """Suggest fixes for invalid packages."""
134
+ if not errors:
135
+ return
136
+
137
+ print("\n" + "=" * 70)
138
+ print("SUGGESTED FIXES:")
139
+ print("=" * 70)
140
+
141
+ for error in errors:
142
+ package = error["package"]
143
+ requested_version = error["version"]
144
+ available = error["available_versions"]
145
+
146
+ print(f"\n{package}=={requested_version}")
147
+
148
+ if available:
149
+ # Find the closest available version
150
+ if requested_version.replace('==', '') in [v.split('rc')[0].split('b')[0].split('a')[0] for v in available]:
151
+ # Pre-release version might exist
152
+ print(f" → Try: {package}=={available[0]}")
153
+ else:
154
+ # Suggest the latest stable version
155
+ stable_versions = [v for v in available if not any(x in v for x in ['rc', 'a', 'b', 'dev'])]
156
+ if stable_versions:
157
+ print(f" → Try: {package}=={stable_versions[0]}")
158
+ else:
159
+ print(f" → Try: {package}=={available[0]}")
160
+ else:
161
+ print(f" → Package might not exist. Check the package name.")
162
+
163
+ def main():
164
+ """Main function to verify requirements file."""
165
+ if len(sys.argv) > 1:
166
+ # Read from file
167
+ filename = sys.argv[1]
168
+ try:
169
+ with open(filename, 'r') as f:
170
+ requirements_text = f.read()
171
+ except FileNotFoundError:
172
+ print(f"Error: File '{filename}' not found")
173
+ sys.exit(1)
174
+ else:
175
+ # Read from stdin or use the example
176
+ print("Paste your requirements.txt content (press Ctrl+D when done):")
177
+ try:
178
+ requirements_text = sys.stdin.read()
179
+ except KeyboardInterrupt:
180
+ print("\nCancelled")
181
+ sys.exit(0)
182
+
183
+ results = verify_requirements(requirements_text)
184
+
185
+ print("\n" + "=" * 70)
186
+ print("SUMMARY:")
187
+ print("=" * 70)
188
+ print(f"Total packages: {results['total']}")
189
+ print(f"Valid packages: {results['valid']} ✅")
190
+ print(f"Invalid packages: {results['invalid']} ❌")
191
+
192
+ if results["errors"]:
193
+ suggest_fixes(results["errors"])
194
+ sys.exit(1)
195
+ else:
196
+ print("\nAll packages and versions are valid! 🎉")
197
+ sys.exit(0)
198
+
199
+ if __name__ == "__main__":
200
+ main()