cleanup_old_code.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #!/usr/bin/env python3
  2. """
  3. 旧代码清理脚本
  4. 此脚本用于安全地删除已废弃的旧代码。
  5. 在运行此脚本之前,请确保:
  6. 1. 新代码已经过充分测试
  7. 2. 所有导入引用已更新
  8. 3. 已创建数据备份
  9. 警告:此操作不可逆!
  10. """
  11. import os
  12. import shutil
  13. from pathlib import Path
  14. from typing import List
  15. import argparse
  16. # 要删除的旧代码目录
  17. OLD_CODE_DIRS = [
  18. 'src/api/sdk',
  19. 'src/api/db',
  20. 'src/api/dataset',
  21. 'src/api/mcp',
  22. ]
  23. # 要保留的文件(用于向后兼容)
  24. KEEP_FILES = [
  25. 'src/api/__init__.py', # 包含废弃警告
  26. 'src/api/DEPRECATED.md', # 废弃说明文档
  27. ]
  28. def list_files_to_delete(dirs: List[str]) -> List[Path]:
  29. """
  30. 列出将要删除的文件
  31. Args:
  32. dirs: 要删除的目录列表
  33. Returns:
  34. 文件路径列表
  35. """
  36. files_to_delete = []
  37. for dir_path in dirs:
  38. path = Path(dir_path)
  39. if path.exists() and path.is_dir():
  40. for file_path in path.rglob('*'):
  41. if file_path.is_file():
  42. files_to_delete.append(file_path)
  43. return files_to_delete
  44. def calculate_size(files: List[Path]) -> int:
  45. """
  46. 计算文件总大小
  47. Args:
  48. files: 文件路径列表
  49. Returns:
  50. 总大小(字节)
  51. """
  52. total_size = 0
  53. for file_path in files:
  54. try:
  55. total_size += file_path.stat().st_size
  56. except Exception:
  57. pass
  58. return total_size
  59. def format_size(size_bytes: int) -> str:
  60. """
  61. 格式化文件大小
  62. Args:
  63. size_bytes: 字节数
  64. Returns:
  65. 格式化的大小字符串
  66. """
  67. for unit in ['B', 'KB', 'MB', 'GB']:
  68. if size_bytes < 1024.0:
  69. return f"{size_bytes:.2f} {unit}"
  70. size_bytes /= 1024.0
  71. return f"{size_bytes:.2f} TB"
  72. def preview_deletion(dry_run: bool = True):
  73. """
  74. 预览将要删除的内容
  75. Args:
  76. dry_run: 是否为演练模式
  77. """
  78. print("=" * 60)
  79. print("Old Code Cleanup Script")
  80. print("=" * 60)
  81. print()
  82. if dry_run:
  83. print("🔍 DRY RUN MODE - No files will be deleted")
  84. else:
  85. print("⚠️ DELETION MODE - Files will be permanently deleted!")
  86. print()
  87. print("Directories to clean:")
  88. for dir_path in OLD_CODE_DIRS:
  89. status = "✓ exists" if Path(dir_path).exists() else "✗ not found"
  90. print(f" - {dir_path} ({status})")
  91. print()
  92. print("Files to keep:")
  93. for file_path in KEEP_FILES:
  94. status = "✓ exists" if Path(file_path).exists() else "✗ not found"
  95. print(f" - {file_path} ({status})")
  96. print()
  97. # 列出将要删除的文件
  98. files_to_delete = list_files_to_delete(OLD_CODE_DIRS)
  99. # 过滤掉要保留的文件
  100. files_to_delete = [
  101. f for f in files_to_delete
  102. if str(f) not in KEEP_FILES
  103. ]
  104. if not files_to_delete:
  105. print("✅ No files to delete")
  106. return
  107. total_size = calculate_size(files_to_delete)
  108. print(f"Files to delete: {len(files_to_delete)}")
  109. print(f"Total size: {format_size(total_size)}")
  110. print()
  111. # 显示前 10 个文件
  112. print("Sample files (first 10):")
  113. for file_path in files_to_delete[:10]:
  114. size = format_size(file_path.stat().st_size)
  115. print(f" - {file_path} ({size})")
  116. if len(files_to_delete) > 10:
  117. print(f" ... and {len(files_to_delete) - 10} more files")
  118. print()
  119. if not dry_run:
  120. # 确认删除
  121. response = input("⚠️ Are you sure you want to delete these files? (yes/no): ")
  122. if response.lower() != 'yes':
  123. print("❌ Deletion cancelled")
  124. return
  125. print()
  126. print("Deleting files...")
  127. deleted_count = 0
  128. for dir_path in OLD_CODE_DIRS:
  129. path = Path(dir_path)
  130. if path.exists() and path.is_dir():
  131. try:
  132. shutil.rmtree(path)
  133. deleted_count += 1
  134. print(f" ✓ Deleted {dir_path}")
  135. except Exception as e:
  136. print(f" ✗ Error deleting {dir_path}: {e}")
  137. print()
  138. print(f"✅ Cleanup complete! Deleted {deleted_count} directories")
  139. print()
  140. print("Next steps:")
  141. print(" 1. Run tests to ensure everything still works")
  142. print(" 2. Commit the changes")
  143. print(" 3. Update documentation if needed")
  144. def main():
  145. """主函数"""
  146. parser = argparse.ArgumentParser(
  147. description='Clean up old deprecated code',
  148. formatter_class=argparse.RawDescriptionHelpFormatter,
  149. epilog="""
  150. Examples:
  151. # Preview what will be deleted (safe)
  152. python scripts/cleanup_old_code.py --dry-run
  153. # Actually delete the files (dangerous!)
  154. python scripts/cleanup_old_code.py --delete
  155. Warning: Deletion is permanent! Make sure you have backups.
  156. """
  157. )
  158. parser.add_argument(
  159. '--dry-run',
  160. action='store_true',
  161. default=True,
  162. help='Preview what will be deleted without actually deleting (default)'
  163. )
  164. parser.add_argument(
  165. '--delete',
  166. action='store_true',
  167. help='Actually delete the files (use with caution!)'
  168. )
  169. args = parser.parse_args()
  170. # 如果指定了 --delete,则不是 dry run
  171. dry_run = not args.delete
  172. preview_deletion(dry_run=dry_run)
  173. if __name__ == '__main__':
  174. main()