codeshift 0.3.3__tar.gz → 0.3.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. {codeshift-0.3.3 → codeshift-0.3.5}/PKG-INFO +46 -4
  2. {codeshift-0.3.3 → codeshift-0.3.5}/README.md +45 -3
  3. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/cli/commands/apply.py +24 -2
  4. codeshift-0.3.5/codeshift/cli/package_manager.py +102 -0
  5. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge/generator.py +11 -1
  6. codeshift-0.3.5/codeshift/knowledge_base/libraries/aiohttp.yaml +186 -0
  7. codeshift-0.3.5/codeshift/knowledge_base/libraries/attrs.yaml +181 -0
  8. codeshift-0.3.5/codeshift/knowledge_base/libraries/celery.yaml +244 -0
  9. codeshift-0.3.5/codeshift/knowledge_base/libraries/click.yaml +195 -0
  10. codeshift-0.3.5/codeshift/knowledge_base/libraries/django.yaml +355 -0
  11. codeshift-0.3.5/codeshift/knowledge_base/libraries/flask.yaml +270 -0
  12. codeshift-0.3.5/codeshift/knowledge_base/libraries/httpx.yaml +183 -0
  13. codeshift-0.3.5/codeshift/knowledge_base/libraries/marshmallow.yaml +238 -0
  14. codeshift-0.3.5/codeshift/knowledge_base/libraries/numpy.yaml +429 -0
  15. codeshift-0.3.5/codeshift/knowledge_base/libraries/pytest.yaml +192 -0
  16. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge_base/libraries/sqlalchemy.yaml +2 -1
  17. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/migrator/engine.py +60 -0
  18. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/migrator/transforms/__init__.py +2 -0
  19. codeshift-0.3.5/codeshift/migrator/transforms/aiohttp_transformer.py +608 -0
  20. codeshift-0.3.5/codeshift/migrator/transforms/attrs_transformer.py +570 -0
  21. codeshift-0.3.5/codeshift/migrator/transforms/celery_transformer.py +546 -0
  22. codeshift-0.3.5/codeshift/migrator/transforms/click_transformer.py +526 -0
  23. codeshift-0.3.5/codeshift/migrator/transforms/django_transformer.py +852 -0
  24. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/migrator/transforms/fastapi_transformer.py +12 -7
  25. codeshift-0.3.5/codeshift/migrator/transforms/flask_transformer.py +505 -0
  26. codeshift-0.3.5/codeshift/migrator/transforms/httpx_transformer.py +419 -0
  27. codeshift-0.3.5/codeshift/migrator/transforms/marshmallow_transformer.py +515 -0
  28. codeshift-0.3.5/codeshift/migrator/transforms/numpy_transformer.py +413 -0
  29. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/migrator/transforms/pydantic_v1_to_v2.py +53 -8
  30. codeshift-0.3.5/codeshift/migrator/transforms/pytest_transformer.py +351 -0
  31. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/migrator/transforms/requests_transformer.py +74 -1
  32. codeshift-0.3.5/codeshift/migrator/transforms/sqlalchemy_transformer.py +828 -0
  33. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift.egg-info/PKG-INFO +46 -4
  34. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift.egg-info/SOURCES.txt +31 -0
  35. {codeshift-0.3.3 → codeshift-0.3.5}/pyproject.toml +1 -1
  36. codeshift-0.3.5/tests/test_aiohttp_transforms.py +197 -0
  37. codeshift-0.3.5/tests/test_attrs_transforms.py +296 -0
  38. codeshift-0.3.5/tests/test_celery_transforms.py +212 -0
  39. codeshift-0.3.5/tests/test_click_transforms.py +211 -0
  40. codeshift-0.3.5/tests/test_django_transforms.py +235 -0
  41. {codeshift-0.3.3 → codeshift-0.3.5}/tests/test_fastapi_transforms.py +82 -8
  42. codeshift-0.3.5/tests/test_flask_transforms.py +206 -0
  43. codeshift-0.3.5/tests/test_httpx_transforms.py +207 -0
  44. codeshift-0.3.5/tests/test_marshmallow_transforms.py +487 -0
  45. codeshift-0.3.5/tests/test_numpy_transforms.py +421 -0
  46. {codeshift-0.3.3 → codeshift-0.3.5}/tests/test_pydantic_transforms.py +93 -0
  47. codeshift-0.3.5/tests/test_pytest_transforms.py +439 -0
  48. {codeshift-0.3.3 → codeshift-0.3.5}/tests/test_requests_transforms.py +36 -0
  49. codeshift-0.3.5/tests/test_sqlalchemy_transforms.py +588 -0
  50. codeshift-0.3.3/codeshift/migrator/transforms/sqlalchemy_transformer.py +0 -175
  51. codeshift-0.3.3/tests/test_sqlalchemy_transforms.py +0 -97
  52. {codeshift-0.3.3 → codeshift-0.3.5}/LICENSE +0 -0
  53. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/__init__.py +0 -0
  54. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/analyzer/__init__.py +0 -0
  55. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/analyzer/risk_assessor.py +0 -0
  56. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/__init__.py +0 -0
  57. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/auth.py +0 -0
  58. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/config.py +0 -0
  59. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/database.py +0 -0
  60. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/main.py +0 -0
  61. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/models/__init__.py +0 -0
  62. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/models/auth.py +0 -0
  63. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/models/billing.py +0 -0
  64. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/models/migrate.py +0 -0
  65. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/models/usage.py +0 -0
  66. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/routers/__init__.py +0 -0
  67. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/routers/auth.py +0 -0
  68. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/routers/billing.py +0 -0
  69. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/routers/migrate.py +0 -0
  70. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/routers/usage.py +0 -0
  71. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/api/routers/webhooks.py +0 -0
  72. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/cli/__init__.py +0 -0
  73. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/cli/commands/__init__.py +0 -0
  74. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/cli/commands/auth.py +0 -0
  75. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/cli/commands/diff.py +0 -0
  76. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/cli/commands/scan.py +0 -0
  77. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/cli/commands/upgrade.py +0 -0
  78. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/cli/commands/upgrade_all.py +0 -0
  79. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/cli/main.py +0 -0
  80. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/cli/quota.py +0 -0
  81. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge/__init__.py +0 -0
  82. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge/cache.py +0 -0
  83. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge/models.py +0 -0
  84. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge/parser.py +0 -0
  85. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge/sources.py +0 -0
  86. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge_base/__init__.py +0 -0
  87. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge_base/libraries/fastapi.yaml +0 -0
  88. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge_base/libraries/pandas.yaml +0 -0
  89. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge_base/libraries/pydantic.yaml +0 -0
  90. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge_base/libraries/requests.yaml +0 -0
  91. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge_base/loader.py +0 -0
  92. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/knowledge_base/models.py +0 -0
  93. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/migrator/__init__.py +0 -0
  94. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/migrator/ast_transforms.py +0 -0
  95. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/migrator/llm_migrator.py +0 -0
  96. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/migrator/transforms/pandas_transformer.py +0 -0
  97. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/scanner/__init__.py +0 -0
  98. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/scanner/code_scanner.py +0 -0
  99. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/scanner/dependency_parser.py +0 -0
  100. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/utils/__init__.py +0 -0
  101. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/utils/api_client.py +0 -0
  102. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/utils/cache.py +0 -0
  103. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/utils/config.py +0 -0
  104. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/utils/llm_client.py +0 -0
  105. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/validator/__init__.py +0 -0
  106. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/validator/syntax_checker.py +0 -0
  107. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift/validator/test_runner.py +0 -0
  108. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift.egg-info/dependency_links.txt +0 -0
  109. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift.egg-info/entry_points.txt +0 -0
  110. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift.egg-info/requires.txt +0 -0
  111. {codeshift-0.3.3 → codeshift-0.3.5}/codeshift.egg-info/top_level.txt +0 -0
  112. {codeshift-0.3.3 → codeshift-0.3.5}/setup.cfg +0 -0
  113. {codeshift-0.3.3 → codeshift-0.3.5}/tests/test_code_scanner.py +0 -0
  114. {codeshift-0.3.3 → codeshift-0.3.5}/tests/test_knowledge_base.py +0 -0
  115. {codeshift-0.3.3 → codeshift-0.3.5}/tests/test_pandas_transforms.py +0 -0
  116. {codeshift-0.3.3 → codeshift-0.3.5}/tests/test_risk_assessor.py +0 -0
  117. {codeshift-0.3.3 → codeshift-0.3.5}/tests/test_syntax_checker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeshift
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: AI-powered CLI tool that migrates Python code to handle breaking dependency changes
5
5
  Author: PyResolve Team
6
6
  License: MIT
@@ -84,6 +84,16 @@ PyResolve is an AI-powered CLI tool that migrates Python code to handle breaking
84
84
  | SQLAlchemy | 1.4 → 2.0 | ✅ Supported |
85
85
  | Pandas | 1.x → 2.x | ✅ Supported |
86
86
  | Requests | Various | ✅ Supported |
87
+ | Django | 3.x → 4.x/5.x | ✅ Supported |
88
+ | Flask | 1.x → 2.x/3.x | ✅ Supported |
89
+ | NumPy | 1.x → 2.x | ✅ Supported |
90
+ | attrs | attr → attrs | ✅ Supported |
91
+ | Celery | 4.x → 5.x | ✅ Supported |
92
+ | Click | 7.x → 8.x | ✅ Supported |
93
+ | aiohttp | 2.x → 3.x | ✅ Supported |
94
+ | httpx | 0.x → 0.24+ | ✅ Supported |
95
+ | Marshmallow | 2.x → 3.x | ✅ Supported |
96
+ | pytest | 6.x → 7.x/8.x | ✅ Supported |
87
97
 
88
98
  ### Any Library (Auto-Generated Knowledge Base)
89
99
 
@@ -104,7 +114,10 @@ pyresolve scan
104
114
  # Scan with detailed breaking change analysis
105
115
  pyresolve scan --fetch-changes
106
116
 
107
- # Analyze and propose changes for a specific library
117
+ # Upgrade all outdated packages at once
118
+ pyresolve upgrade-all
119
+
120
+ # Or analyze and propose changes for a specific library
108
121
  pyresolve upgrade pydantic --target 2.5.0
109
122
 
110
123
  # View detailed diff of proposed changes
@@ -231,6 +244,35 @@ pyresolve apply
231
244
  # --file, -f Apply changes to specific file only
232
245
  ```
233
246
 
247
+ ### Upgrade-All Command
248
+
249
+ Upgrade all outdated packages to their latest versions in one go:
250
+
251
+ ```bash
252
+ pyresolve upgrade-all
253
+
254
+ # Options:
255
+ # --all, -a Include all outdated packages (not just Tier 1)
256
+ # --path, -p Path to analyze (default: current directory)
257
+ # --dry-run Show what would be changed without saving state
258
+ ```
259
+
260
+ ### Libraries Command
261
+
262
+ List all supported libraries and their migration paths:
263
+
264
+ ```bash
265
+ pyresolve libraries
266
+ ```
267
+
268
+ ### Status Command
269
+
270
+ Show current migration status, pending changes, and quota information:
271
+
272
+ ```bash
273
+ pyresolve status
274
+ ```
275
+
234
276
  ## How It Works
235
277
 
236
278
  ```text
@@ -261,7 +303,7 @@ pyresolve apply
261
303
  2. **Parse Changes**: Uses LLM to extract breaking changes with confidence levels (HIGH/MEDIUM/LOW)
262
304
  3. **Scan Codebase**: Finds imports and usage of the target library
263
305
  4. **Tiered Migration**:
264
- - **Tier 1**: Deterministic AST transforms for known libraries (pydantic, fastapi, sqlalchemy, pandas, requests)
306
+ - **Tier 1**: Deterministic AST transforms for 15 supported libraries (Pydantic, FastAPI, SQLAlchemy, Django, Flask, NumPy, Pandas, Requests, attrs, Celery, Click, aiohttp, httpx, Marshmallow, pytest)
265
307
  - **Tier 2**: Knowledge base guided migration with LLM assistance
266
308
  - **Tier 3**: Pure LLM migration for unknown patterns
267
309
  5. **Validate**: Runs syntax checks and optionally your test suite
@@ -303,7 +345,7 @@ PyResolve uses a tiered pricing model:
303
345
 
304
346
  | Tier | Price | Features |
305
347
  |------|-------|----------|
306
- | **Free** | $0/month | Tier 1 deterministic transforms (Pydantic, FastAPI, SQLAlchemy, Pandas, Requests) |
348
+ | **Free** | $0/month | Tier 1 deterministic transforms (15 libraries including Pydantic, Django, Flask, SQLAlchemy, and more) |
307
349
  | **Pro** | $19/month | Tier 2 KB-guided LLM migrations for any library |
308
350
  | **Unlimited** | $49/month | Tier 3 pure LLM migrations + priority support |
309
351
 
@@ -28,6 +28,16 @@ PyResolve is an AI-powered CLI tool that migrates Python code to handle breaking
28
28
  | SQLAlchemy | 1.4 → 2.0 | ✅ Supported |
29
29
  | Pandas | 1.x → 2.x | ✅ Supported |
30
30
  | Requests | Various | ✅ Supported |
31
+ | Django | 3.x → 4.x/5.x | ✅ Supported |
32
+ | Flask | 1.x → 2.x/3.x | ✅ Supported |
33
+ | NumPy | 1.x → 2.x | ✅ Supported |
34
+ | attrs | attr → attrs | ✅ Supported |
35
+ | Celery | 4.x → 5.x | ✅ Supported |
36
+ | Click | 7.x → 8.x | ✅ Supported |
37
+ | aiohttp | 2.x → 3.x | ✅ Supported |
38
+ | httpx | 0.x → 0.24+ | ✅ Supported |
39
+ | Marshmallow | 2.x → 3.x | ✅ Supported |
40
+ | pytest | 6.x → 7.x/8.x | ✅ Supported |
31
41
 
32
42
  ### Any Library (Auto-Generated Knowledge Base)
33
43
 
@@ -48,7 +58,10 @@ pyresolve scan
48
58
  # Scan with detailed breaking change analysis
49
59
  pyresolve scan --fetch-changes
50
60
 
51
- # Analyze and propose changes for a specific library
61
+ # Upgrade all outdated packages at once
62
+ pyresolve upgrade-all
63
+
64
+ # Or analyze and propose changes for a specific library
52
65
  pyresolve upgrade pydantic --target 2.5.0
53
66
 
54
67
  # View detailed diff of proposed changes
@@ -175,6 +188,35 @@ pyresolve apply
175
188
  # --file, -f Apply changes to specific file only
176
189
  ```
177
190
 
191
+ ### Upgrade-All Command
192
+
193
+ Upgrade all outdated packages to their latest versions in one go:
194
+
195
+ ```bash
196
+ pyresolve upgrade-all
197
+
198
+ # Options:
199
+ # --all, -a Include all outdated packages (not just Tier 1)
200
+ # --path, -p Path to analyze (default: current directory)
201
+ # --dry-run Show what would be changed without saving state
202
+ ```
203
+
204
+ ### Libraries Command
205
+
206
+ List all supported libraries and their migration paths:
207
+
208
+ ```bash
209
+ pyresolve libraries
210
+ ```
211
+
212
+ ### Status Command
213
+
214
+ Show current migration status, pending changes, and quota information:
215
+
216
+ ```bash
217
+ pyresolve status
218
+ ```
219
+
178
220
  ## How It Works
179
221
 
180
222
  ```text
@@ -205,7 +247,7 @@ pyresolve apply
205
247
  2. **Parse Changes**: Uses LLM to extract breaking changes with confidence levels (HIGH/MEDIUM/LOW)
206
248
  3. **Scan Codebase**: Finds imports and usage of the target library
207
249
  4. **Tiered Migration**:
208
- - **Tier 1**: Deterministic AST transforms for known libraries (pydantic, fastapi, sqlalchemy, pandas, requests)
250
+ - **Tier 1**: Deterministic AST transforms for 15 supported libraries (Pydantic, FastAPI, SQLAlchemy, Django, Flask, NumPy, Pandas, Requests, attrs, Celery, Click, aiohttp, httpx, Marshmallow, pytest)
209
251
  - **Tier 2**: Knowledge base guided migration with LLM assistance
210
252
  - **Tier 3**: Pure LLM migration for unknown patterns
211
253
  5. **Validate**: Runs syntax checks and optionally your test suite
@@ -247,7 +289,7 @@ PyResolve uses a tiered pricing model:
247
289
 
248
290
  | Tier | Price | Features |
249
291
  |------|-------|----------|
250
- | **Free** | $0/month | Tier 1 deterministic transforms (Pydantic, FastAPI, SQLAlchemy, Pandas, Requests) |
292
+ | **Free** | $0/month | Tier 1 deterministic transforms (15 libraries including Pydantic, Django, Flask, SQLAlchemy, and more) |
251
293
  | **Pro** | $19/month | Tier 2 KB-guided LLM migrations for any library |
252
294
  | **Unlimited** | $49/month | Tier 3 pure LLM migrations + priority support |
253
295
 
@@ -10,6 +10,7 @@ from rich.panel import Panel
10
10
  from rich.prompt import Confirm
11
11
 
12
12
  from codeshift.cli.commands.upgrade import load_state, save_state
13
+ from codeshift.cli.package_manager import get_install_commands, get_sync_command
13
14
  from codeshift.cli.quota import (
14
15
  QuotaError,
15
16
  check_quota,
@@ -226,11 +227,32 @@ def apply(
226
227
  state_file.unlink()
227
228
  console.print("\n[green]Migration complete![/]")
228
229
 
229
- # Next steps
230
+ # Next steps - generate dynamic dependency sync command
230
231
  console.print("\n[bold]Recommended next steps:[/]")
231
232
  console.print(" 1. Review the changes in your editor")
232
233
  console.print(" 2. Run your test suite: [cyan]pytest[/]")
233
- console.print(" 3. Update your dependencies: [cyan]pip install pydantic>=2.0[/]")
234
+
235
+ # Generate dependency update commands based on library/libraries and package manager
236
+ sync_command = get_sync_command(project_path)
237
+
238
+ # Check if this is a multi-library migration (upgrade-all)
239
+ migrations = state.get("migrations", [])
240
+ if library == "multiple" and migrations:
241
+ # Multi-library case: show sync command and list all libraries
242
+ console.print(f" 3. Sync your dependencies: [cyan]{sync_command}[/]")
243
+ console.print("\n [dim]Upgraded libraries:[/]")
244
+ for migration in migrations:
245
+ lib_name = migration.get("library", "unknown")
246
+ to_version = migration.get("to_version", "unknown")
247
+ console.print(f" • {lib_name} → {to_version}")
248
+ else:
249
+ # Single library case: show sync command with specific library info
250
+ console.print(f" 3. Sync your dependencies: [cyan]{sync_command}[/]")
251
+ if library != "unknown" and target_version != "unknown":
252
+ libraries = [{"name": library, "version": target_version}]
253
+ install_commands = get_install_commands(project_path, libraries)
254
+ if install_commands:
255
+ console.print(f"\n [dim]Or install directly:[/] {install_commands[0]}")
234
256
 
235
257
 
236
258
  @click.command()
@@ -0,0 +1,102 @@
1
+ """Package manager detection and sync command generation utilities."""
2
+
3
+ import shutil
4
+ from pathlib import Path
5
+ from typing import Literal
6
+
7
+ PackageManager = Literal["uv", "poetry", "pip"]
8
+
9
+
10
+ def detect_package_manager(project_path: Path) -> PackageManager:
11
+ """Detect the package manager used in a project.
12
+
13
+ Detection order:
14
+ 1. uv.lock file presence → uv
15
+ 2. poetry.lock file presence → poetry
16
+ 3. Default → pip
17
+
18
+ Args:
19
+ project_path: Path to the project root directory.
20
+
21
+ Returns:
22
+ The detected package manager name.
23
+ """
24
+ # Check for uv (uv.lock file)
25
+ if (project_path / "uv.lock").exists():
26
+ return "uv"
27
+
28
+ # Check for poetry (poetry.lock file)
29
+ if (project_path / "poetry.lock").exists():
30
+ return "poetry"
31
+
32
+ # Default to pip
33
+ return "pip"
34
+
35
+
36
+ def get_sync_command(project_path: Path) -> str:
37
+ """Get the appropriate dependency sync command for the project.
38
+
39
+ Args:
40
+ project_path: Path to the project root directory.
41
+
42
+ Returns:
43
+ The shell command to sync/install dependencies.
44
+ """
45
+ manager = detect_package_manager(project_path)
46
+
47
+ if manager == "uv":
48
+ return "uv sync"
49
+ elif manager == "poetry":
50
+ return "poetry install"
51
+ else:
52
+ # pip - check what kind of project it is
53
+ if (project_path / "pyproject.toml").exists():
54
+ return "pip install -e ."
55
+ elif (project_path / "requirements.txt").exists():
56
+ return "pip install -r requirements.txt"
57
+ else:
58
+ return "pip install -e ."
59
+
60
+
61
+ def is_package_manager_available(manager: PackageManager) -> bool:
62
+ """Check if a package manager is available in the system.
63
+
64
+ Args:
65
+ manager: The package manager to check.
66
+
67
+ Returns:
68
+ True if the package manager is available, False otherwise.
69
+ """
70
+ return shutil.which(manager) is not None
71
+
72
+
73
+ def get_install_commands(
74
+ project_path: Path,
75
+ libraries: list[dict[str, str]],
76
+ ) -> list[str]:
77
+ """Generate install commands for the upgraded libraries.
78
+
79
+ This is a fallback for when users want to install specific packages
80
+ rather than sync the entire project.
81
+
82
+ Args:
83
+ project_path: Path to the project root directory.
84
+ libraries: List of dicts with 'name' and 'version' keys.
85
+
86
+ Returns:
87
+ List of install commands for each library.
88
+ """
89
+ manager = detect_package_manager(project_path)
90
+
91
+ commands = []
92
+ for lib in libraries:
93
+ name = lib["name"]
94
+ version = lib["version"]
95
+ if manager == "uv":
96
+ commands.append(f"uv add {name}>={version}")
97
+ elif manager == "poetry":
98
+ commands.append(f"poetry add {name}>={version}")
99
+ else:
100
+ commands.append(f"pip install {name}>={version}")
101
+
102
+ return commands
@@ -162,7 +162,17 @@ class KnowledgeGenerator:
162
162
 
163
163
 
164
164
  # Tier 1 libraries with deterministic AST transforms
165
- TIER_1_LIBRARIES = {"pydantic", "fastapi", "sqlalchemy", "pandas", "requests"}
165
+ TIER_1_LIBRARIES = {
166
+ "pydantic",
167
+ "fastapi",
168
+ "sqlalchemy",
169
+ "pandas",
170
+ "requests",
171
+ "numpy",
172
+ "pytest",
173
+ "marshmallow",
174
+ "flask",
175
+ }
166
176
 
167
177
 
168
178
  def is_tier_1_library(library: str) -> bool:
@@ -0,0 +1,186 @@
1
+ # aiohttp Knowledge Base
2
+ # Breaking changes from v3.7 to v3.9+
3
+
4
+ name: aiohttp
5
+ display_name: aiohttp
6
+ description: Async HTTP client/server framework for asyncio
7
+ migration_guide_url: https://docs.aiohttp.org/en/stable/changes.html
8
+
9
+ supported_migrations:
10
+ - from: "3.7"
11
+ to: "3.9"
12
+
13
+ breaking_changes:
14
+ # Loop parameter removal - ClientSession
15
+ - symbol: "ClientSession(loop=...)"
16
+ change_type: removed
17
+ severity: high
18
+ from_version: "3.7"
19
+ to_version: "3.8"
20
+ description: "loop parameter removed from ClientSession constructor"
21
+ replacement: "ClientSession()"
22
+ has_deterministic_transform: true
23
+ transform_name: remove_loop_param_client_session
24
+ notes: "Event loop is now obtained automatically via asyncio.get_event_loop()"
25
+
26
+ # Loop parameter removal - TCPConnector
27
+ - symbol: "TCPConnector(loop=...)"
28
+ change_type: removed
29
+ severity: high
30
+ from_version: "3.7"
31
+ to_version: "3.8"
32
+ description: "loop parameter removed from TCPConnector constructor"
33
+ replacement: "TCPConnector()"
34
+ has_deterministic_transform: true
35
+ transform_name: remove_loop_param_tcp_connector
36
+
37
+ # Loop parameter removal - UnixConnector
38
+ - symbol: "UnixConnector(loop=...)"
39
+ change_type: removed
40
+ severity: medium
41
+ from_version: "3.7"
42
+ to_version: "3.8"
43
+ description: "loop parameter removed from UnixConnector constructor"
44
+ replacement: "UnixConnector()"
45
+ has_deterministic_transform: true
46
+ transform_name: remove_loop_param_unix_connector
47
+
48
+ # Loop parameter removal - web.Application
49
+ - symbol: "web.Application(loop=...)"
50
+ change_type: removed
51
+ severity: high
52
+ from_version: "3.7"
53
+ to_version: "3.8"
54
+ description: "loop parameter removed from web.Application constructor"
55
+ replacement: "web.Application()"
56
+ has_deterministic_transform: true
57
+ transform_name: remove_loop_param_web_application
58
+
59
+ # Loop parameter removal - ClientTimeout
60
+ - symbol: "ClientTimeout(loop=...)"
61
+ change_type: removed
62
+ severity: medium
63
+ from_version: "3.7"
64
+ to_version: "3.8"
65
+ description: "loop parameter removed from ClientTimeout constructor"
66
+ replacement: "ClientTimeout()"
67
+ has_deterministic_transform: true
68
+ transform_name: remove_loop_param_client_timeout
69
+
70
+ # connector_owner default change
71
+ - symbol: "ClientSession(connector=..., connector_owner=None)"
72
+ change_type: behavior_change
73
+ severity: medium
74
+ from_version: "3.7"
75
+ to_version: "3.9"
76
+ description: "connector_owner now defaults to True; explicitly set to False if connector is shared"
77
+ replacement: "ClientSession(connector=..., connector_owner=False)"
78
+ has_deterministic_transform: false
79
+ notes: "Manual review needed - depends on whether connector is shared across sessions"
80
+
81
+ # BasicAuth.encode() removal
82
+ - symbol: "BasicAuth.encode()"
83
+ change_type: removed
84
+ severity: medium
85
+ from_version: "3.7"
86
+ to_version: "3.9"
87
+ description: "BasicAuth.encode() method removed"
88
+ replacement: "str(BasicAuth(...))"
89
+ has_deterministic_transform: true
90
+ transform_name: basicauth_encode_to_str
91
+
92
+ # Deprecated timeout parameters
93
+ - symbol: "ClientSession(read_timeout=...)"
94
+ change_type: removed
95
+ severity: medium
96
+ from_version: "3.7"
97
+ to_version: "3.8"
98
+ description: "read_timeout parameter deprecated, use ClientTimeout instead"
99
+ replacement: "ClientSession(timeout=ClientTimeout(total=...))"
100
+ has_deterministic_transform: true
101
+ transform_name: read_timeout_to_client_timeout
102
+
103
+ - symbol: "ClientSession(conn_timeout=...)"
104
+ change_type: removed
105
+ severity: medium
106
+ from_version: "3.7"
107
+ to_version: "3.8"
108
+ description: "conn_timeout parameter deprecated, use ClientTimeout instead"
109
+ replacement: "ClientSession(timeout=ClientTimeout(connect=...))"
110
+ has_deterministic_transform: true
111
+ transform_name: conn_timeout_to_client_timeout
112
+
113
+ # app.loop, request.loop, client.loop deprecation
114
+ - symbol: "app.loop"
115
+ change_type: deprecated
116
+ severity: medium
117
+ from_version: "3.7"
118
+ to_version: "3.8"
119
+ description: "app.loop property deprecated"
120
+ replacement: "asyncio.get_event_loop()"
121
+ has_deterministic_transform: true
122
+ transform_name: app_loop_to_get_event_loop
123
+
124
+ - symbol: "request.app.loop"
125
+ change_type: deprecated
126
+ severity: medium
127
+ from_version: "3.7"
128
+ to_version: "3.8"
129
+ description: "request.app.loop property deprecated"
130
+ replacement: "asyncio.get_event_loop()"
131
+ has_deterministic_transform: true
132
+ transform_name: request_loop_to_get_event_loop
133
+
134
+ # Middleware signature changes (old-style to new-style)
135
+ - symbol: "@middleware"
136
+ change_type: signature_change
137
+ severity: high
138
+ from_version: "3.7"
139
+ to_version: "3.9"
140
+ description: "Old-style middleware decorator deprecated; use @web.middleware with async def(request, handler)"
141
+ replacement: "@web.middleware async def middleware(request, handler)"
142
+ has_deterministic_transform: false
143
+ notes: "Middleware function signature changed; manual review recommended"
144
+
145
+ # ws_connect timeout deprecation
146
+ - symbol: "ws_connect(timeout=...)"
147
+ change_type: deprecated
148
+ severity: low
149
+ from_version: "3.7"
150
+ to_version: "3.9"
151
+ description: "timeout parameter in ws_connect deprecated"
152
+ replacement: "ws_connect(receive_timeout=...)"
153
+ has_deterministic_transform: true
154
+ transform_name: ws_connect_timeout_rename
155
+
156
+ - symbol: "ws_connect(receive_timeout=...)"
157
+ change_type: behavior_change
158
+ severity: low
159
+ from_version: "3.7"
160
+ to_version: "3.9"
161
+ description: "Default websocket receive_timeout changed from None to 10.0 seconds"
162
+ replacement: "ws_connect(receive_timeout=None)"
163
+ has_deterministic_transform: false
164
+ notes: "Set receive_timeout=None explicitly if you want no timeout"
165
+
166
+ # Response URL attribute change
167
+ - symbol: "response.url_obj"
168
+ change_type: renamed
169
+ severity: low
170
+ from_version: "3.7"
171
+ to_version: "3.9"
172
+ description: "url_obj attribute renamed to url (now returns yarl.URL)"
173
+ replacement: "response.url"
174
+ has_deterministic_transform: true
175
+ transform_name: url_obj_to_url
176
+
177
+ # WebSocket protocol attribute rename
178
+ - symbol: "ws_response.protocol"
179
+ change_type: renamed
180
+ severity: low
181
+ from_version: "3.7"
182
+ to_version: "3.9"
183
+ description: "WebSocketResponse.protocol renamed to ws_protocol"
184
+ replacement: "ws_response.ws_protocol"
185
+ has_deterministic_transform: true
186
+ transform_name: ws_protocol_rename