rcoder 1.0.0__py3-none-any.whl

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.
rcoder/remote_tools.py ADDED
@@ -0,0 +1,434 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Rcoder 远程工具模块
4
+ 针对远程编程场景的优化,特别是远程主机直接下载文件的功能
5
+ """
6
+
7
+ import time
8
+ import asyncio
9
+ from typing import Optional, List, Dict, Any
10
+
11
+ class RemoteTools:
12
+ """
13
+ 远程工具类
14
+ 提供针对远程编程场景的优化工具
15
+ """
16
+
17
+ def __init__(self, remote_host):
18
+ """
19
+ 初始化远程工具
20
+
21
+ Args:
22
+ remote_host: RemoteHost实例
23
+ """
24
+ self.remote_host = remote_host
25
+
26
+ def download_file(self, url: str, destination: str, use_cache: bool = False) -> str:
27
+ """
28
+ 在远程主机上下载文件
29
+ 优化:直接在远程主机上下载,避免通过本地中转
30
+
31
+ Args:
32
+ url: 文件下载URL
33
+ destination: 保存路径
34
+ use_cache: 是否使用缓存
35
+ """
36
+ # 检查URL类型,使用合适的下载工具
37
+ download_cmd = ""
38
+
39
+ # 检查远程主机是否有wget或curl
40
+ has_wget = 'wget' in self.remote_host.run('which wget', use_cache=True)
41
+ has_curl = 'curl' in self.remote_host.run('which curl', use_cache=True)
42
+
43
+ if has_wget:
44
+ # 使用wget下载,添加重试和断点续传
45
+ download_cmd = f"wget -c --tries=5 --timeout=30 '{url}' -O '{destination}'"
46
+ elif has_curl:
47
+ # 使用curl下载,添加重试
48
+ download_cmd = f"curl -L --retry 5 --connect-timeout 30 '{url}' -o '{destination}'"
49
+ else:
50
+ # 尝试使用Python下载
51
+ download_cmd = f"python3 -c \"import urllib.request; urllib.request.urlretrieve('{url}', '{destination}')\""
52
+
53
+ # 执行下载命令
54
+ print(f"📥 开始下载文件: {url}")
55
+ print(f"💾 保存到: {destination}")
56
+
57
+ start_time = time.time()
58
+ result = self.remote_host.run(download_cmd, use_cache=use_cache)
59
+ execution_time = time.time() - start_time
60
+
61
+ print(f"✅ 下载完成 (耗时: {execution_time:.1f}秒)")
62
+ return result
63
+
64
+ async def download_file_async(self, url: str, destination: str, use_cache: bool = False) -> str:
65
+ """
66
+ 异步在远程主机上下载文件
67
+ """
68
+ return await self.remote_host.run_async(
69
+ f"wget -c --tries=5 --timeout=30 '{url}' -O '{destination}'",
70
+ use_cache=use_cache
71
+ )
72
+
73
+ def download_github_repo(self, repo_url: str, destination: str = '.',
74
+ branch: Optional[str] = None, use_cache: bool = False) -> str:
75
+ """
76
+ 在远程主机上克隆GitHub仓库
77
+ 优化:直接在远程主机上克隆,避免通过本地中转
78
+
79
+ Args:
80
+ repo_url: GitHub仓库URL
81
+ destination: 保存路径
82
+ branch: 分支名称
83
+ use_cache: 是否使用缓存
84
+ """
85
+ # 检查是否有git
86
+ has_git = 'git' in self.remote_host.run('which git', use_cache=True)
87
+
88
+ if not has_git:
89
+ return "错误: 远程主机未安装git"
90
+
91
+ # 构建git克隆命令
92
+ git_cmd = "git clone"
93
+ if branch:
94
+ git_cmd += f" -b {branch}"
95
+ git_cmd += f" --depth 1 '{repo_url}' '{destination}'"
96
+
97
+ print(f"📥 开始克隆GitHub仓库: {repo_url}")
98
+ if branch:
99
+ print(f"🌿 分支: {branch}")
100
+ print(f"💾 保存到: {destination}")
101
+
102
+ start_time = time.time()
103
+ result = self.remote_host.run(git_cmd, use_cache=use_cache)
104
+ execution_time = time.time() - start_time
105
+
106
+ print(f"✅ 克隆完成 (耗时: {execution_time:.1f}秒)")
107
+ return result
108
+
109
+ async def download_github_repo_async(self, repo_url: str, destination: str = '.',
110
+ branch: Optional[str] = None, use_cache: bool = False) -> str:
111
+ """
112
+ 异步在远程主机上克隆GitHub仓库
113
+ """
114
+ git_cmd = "git clone"
115
+ if branch:
116
+ git_cmd += f" -b {branch}"
117
+ git_cmd += f" --depth 1 '{repo_url}' '{destination}'"
118
+
119
+ return await self.remote_host.run_async(git_cmd, use_cache=use_cache)
120
+
121
+ def install_python_package(self, package: str, version: Optional[str] = None,
122
+ use_pip3: bool = True, use_cache: bool = False) -> str:
123
+ """
124
+ 在远程主机上安装Python包
125
+ 优化:直接在远程主机上安装,避免通过本地中转
126
+
127
+ Args:
128
+ package: 包名
129
+ version: 版本号
130
+ use_pip3: 是否使用pip3
131
+ use_cache: 是否使用缓存
132
+ """
133
+ # 构建pip命令
134
+ pip_cmd = "pip3" if use_pip3 else "pip"
135
+ install_cmd = f"{pip_cmd} install --no-cache-dir"
136
+
137
+ if version:
138
+ install_cmd += f" '{package}=={version}'"
139
+ else:
140
+ install_cmd += f" '{package}'"
141
+
142
+ print(f"📦 开始安装Python包: {package}")
143
+ if version:
144
+ print(f"🔢 版本: {version}")
145
+
146
+ start_time = time.time()
147
+ result = self.remote_host.run(install_cmd, use_cache=use_cache)
148
+ execution_time = time.time() - start_time
149
+
150
+ print(f"✅ 安装完成 (耗时: {execution_time:.1f}秒)")
151
+ return result
152
+
153
+ async def install_python_package_async(self, package: str, version: Optional[str] = None,
154
+ use_pip3: bool = True, use_cache: bool = False) -> str:
155
+ """
156
+ 异步在远程主机上安装Python包
157
+ """
158
+ pip_cmd = "pip3" if use_pip3 else "pip"
159
+ install_cmd = f"{pip_cmd} install --no-cache-dir"
160
+
161
+ if version:
162
+ install_cmd += f" '{package}=={version}'"
163
+ else:
164
+ install_cmd += f" '{package}'"
165
+
166
+ return await self.remote_host.run_async(install_cmd, use_cache=use_cache)
167
+
168
+ def install_python_packages(self, packages: List[str], use_pip3: bool = True,
169
+ use_cache: bool = False) -> Dict[str, str]:
170
+ """
171
+ 在远程主机上批量安装Python包
172
+
173
+ Args:
174
+ packages: 包名列表
175
+ use_pip3: 是否使用pip3
176
+ use_cache: 是否使用缓存
177
+ """
178
+ results = {}
179
+ pip_cmd = "pip3" if use_pip3 else "pip"
180
+
181
+ print(f"📦 开始批量安装Python包 ({len(packages)}个)")
182
+
183
+ for package in packages:
184
+ install_cmd = f"{pip_cmd} install --no-cache-dir '{package}'"
185
+ print(f" - 安装: {package}")
186
+
187
+ try:
188
+ result = self.remote_host.run(install_cmd, use_cache=use_cache)
189
+ results[package] = result
190
+ print(f" ✅ 成功")
191
+ except Exception as e:
192
+ results[package] = f"错误: {e}"
193
+ print(f" ❌ 失败: {e}")
194
+
195
+ print(f"✅ 批量安装完成")
196
+ return results
197
+
198
+ async def install_python_packages_async(self, packages: List[str], use_pip3: bool = True,
199
+ use_cache: bool = False) -> Dict[str, str]:
200
+ """
201
+ 异步在远程主机上批量安装Python包
202
+ """
203
+ tasks = []
204
+ pip_cmd = "pip3" if use_pip3 else "pip"
205
+
206
+ for package in packages:
207
+ install_cmd = f"{pip_cmd} install --no-cache-dir '{package}'"
208
+ task = self.remote_host.run_async(install_cmd, use_cache=use_cache)
209
+ tasks.append(task)
210
+
211
+ results = await asyncio.gather(*tasks)
212
+ return dict(zip(packages, results))
213
+
214
+ def update_system_packages(self, use_cache: bool = False) -> str:
215
+ """
216
+ 在远程主机上更新系统包
217
+
218
+ Args:
219
+ use_cache: 是否使用缓存
220
+ """
221
+ # 检查系统类型
222
+ os_type = self.remote_host.run('uname -s', use_cache=True).strip()
223
+
224
+ update_cmd = ""
225
+ if 'Linux' in os_type:
226
+ # 检查包管理器
227
+ has_apt = 'apt' in self.remote_host.run('which apt', use_cache=True)
228
+ has_yum = 'yum' in self.remote_host.run('which yum', use_cache=True)
229
+ has_dnf = 'dnf' in self.remote_host.run('which dnf', use_cache=True)
230
+
231
+ if has_apt:
232
+ update_cmd = "sudo apt update && sudo apt upgrade -y"
233
+ elif has_dnf:
234
+ update_cmd = "sudo dnf update -y"
235
+ elif has_yum:
236
+ update_cmd = "sudo yum update -y"
237
+ else:
238
+ return "错误: 无法识别的Linux包管理器"
239
+ else:
240
+ return f"错误: 不支持的操作系统: {os_type}"
241
+
242
+ print("🔄 开始更新系统包")
243
+
244
+ start_time = time.time()
245
+ result = self.remote_host.run(update_cmd, use_cache=use_cache)
246
+ execution_time = time.time() - start_time
247
+
248
+ print(f"✅ 系统包更新完成 (耗时: {execution_time:.1f}秒)")
249
+ return result
250
+
251
+ def download_pypi_package(self, package: str, version: Optional[str] = None,
252
+ destination: str = '.', use_cache: bool = False) -> str:
253
+ """
254
+ 在远程主机上下载PyPI包
255
+ 优化:直接在远程主机上下载,避免通过本地中转
256
+
257
+ Args:
258
+ package: 包名
259
+ version: 版本号
260
+ destination: 保存路径
261
+ use_cache: 是否使用缓存
262
+ """
263
+ # 构建下载URL
264
+ if version:
265
+ url = f"https://pypi.org/packages/source/{package[0]}/{package}/{package}-{version}.tar.gz"
266
+ else:
267
+ # 获取最新版本
268
+ version_cmd = f"python3 -c \"import json, urllib.request; print(json.loads(urllib.request.urlopen('https://pypi.org/pypi/{package}/json').read())['info']['version'])\""
269
+ version = self.remote_host.run(version_cmd, use_cache=use_cache).strip()
270
+ url = f"https://pypi.org/packages/source/{package[0]}/{package}/{package}-{version}.tar.gz"
271
+
272
+ # 下载文件
273
+ return self.download_file(url, f"{destination}/{package}-{version}.tar.gz", use_cache)
274
+
275
+ def setup_development_environment(self, python_version: str = '3.8',
276
+ packages: Optional[List[str]] = None,
277
+ use_cache: bool = False) -> Dict[str, str]:
278
+ """
279
+ 在远程主机上设置开发环境
280
+
281
+ Args:
282
+ python_version: Python版本
283
+ packages: 要安装的Python包列表
284
+ use_cache: 是否使用缓存
285
+ """
286
+ results = {}
287
+
288
+ print("🚀 开始设置开发环境")
289
+
290
+ # 更新系统包
291
+ results['system_update'] = self.update_system_packages(use_cache)
292
+ print()
293
+
294
+ # 安装Python和开发工具
295
+ os_type = self.remote_host.run('uname -s', use_cache=True).strip()
296
+
297
+ if 'Linux' in os_type:
298
+ has_apt = 'apt' in self.remote_host.run('which apt', use_cache=True)
299
+ has_yum = 'yum' in self.remote_host.run('which yum', use_cache=True)
300
+ has_dnf = 'dnf' in self.remote_host.run('which dnf', use_cache=True)
301
+
302
+ if has_apt:
303
+ dev_tools_cmd = "sudo apt install -y python3 python3-pip python3-venv build-essential git"
304
+ elif has_dnf:
305
+ dev_tools_cmd = "sudo dnf install -y python3 python3-pip python3-venv gcc git"
306
+ elif has_yum:
307
+ dev_tools_cmd = "sudo yum install -y python3 python3-pip python3-venv gcc git"
308
+ else:
309
+ results['dev_tools'] = "错误: 无法识别的Linux包管理器"
310
+ return results
311
+
312
+ print("📦 安装开发工具")
313
+ results['dev_tools'] = self.remote_host.run(dev_tools_cmd, use_cache=use_cache)
314
+ print("✅ 开发工具安装完成")
315
+ print()
316
+
317
+ # 安装Python包
318
+ if packages:
319
+ print(f"📦 安装Python包 ({len(packages)}个)")
320
+ results['python_packages'] = self.install_python_packages(packages, use_cache=use_cache)
321
+ print()
322
+
323
+ # 验证环境
324
+ print("🔍 验证开发环境")
325
+ results['python_version'] = self.remote_host.run('python3 --version', use_cache=use_cache)
326
+ results['pip_version'] = self.remote_host.run('pip3 --version', use_cache=use_cache)
327
+ results['git_version'] = self.remote_host.run('git --version', use_cache=use_cache)
328
+
329
+ print("✅ 开发环境设置完成")
330
+ return results
331
+
332
+ def optimize_remote_connection(self, use_cache: bool = True) -> str:
333
+ """
334
+ 优化远程主机的网络连接
335
+
336
+ Args:
337
+ use_cache: 是否使用缓存
338
+ """
339
+ print("⚡ 开始优化远程连接")
340
+
341
+ # 检查系统类型
342
+ os_type = self.remote_host.run('uname -s', use_cache=use_cache).strip()
343
+
344
+ if 'Linux' in os_type:
345
+ # 优化SSH连接
346
+ ssh_opt_cmd = """
347
+ sudo bash -c 'cat >> /etc/ssh/ssh_config << EOF\n\n# Rcoder 优化设置\nServerAliveInterval 30\nServerAliveCountMax 10\nCompression yes\nTCPKeepAlive yes\nEOF'
348
+ """
349
+
350
+ # 优化系统网络设置
351
+ net_opt_cmd = """
352
+ sudo bash -c 'cat >> /etc/sysctl.conf << EOF\n\n# Rcoder 网络优化\nnet.core.rmem_max=16777216\nnet.core.wmem_max=16777216\nnet.ipv4.tcp_rmem=4096 87380 16777216\nnet.ipv4.tcp_wmem=4096 65536 16777216\nnet.ipv4.tcp_window_scaling=1\nnet.ipv4.tcp_timestamps=1\nnet.ipv4.tcp_slow_start_after_idle=0\nEOF'
353
+ sudo sysctl -p
354
+ """
355
+
356
+ print("🔧 优化SSH连接设置")
357
+ ssh_result = self.remote_host.run(ssh_opt_cmd, use_cache=use_cache)
358
+
359
+ print("🔧 优化系统网络设置")
360
+ net_result = self.remote_host.run(net_opt_cmd, use_cache=use_cache)
361
+
362
+ print("✅ 远程连接优化完成")
363
+ return f"SSH优化: {ssh_result}\n网络优化: {net_result}"
364
+ else:
365
+ return f"错误: 不支持的操作系统: {os_type}"
366
+
367
+ def create_project(self, project_name: str, template: str = 'basic',
368
+ use_cache: bool = False) -> str:
369
+ """
370
+ 在远程主机上创建项目
371
+
372
+ Args:
373
+ project_name: 项目名称
374
+ template: 模板类型 (basic, flask, django, fastapi)
375
+ use_cache: 是否使用缓存
376
+ """
377
+ print(f"🏗️ 开始创建项目: {project_name}")
378
+ print(f"📋 模板: {template}")
379
+
380
+ # 创建项目目录
381
+ self.remote_host.run(f"mkdir -p {project_name}", use_cache=use_cache)
382
+
383
+ if template == 'basic':
384
+ # 创建基本项目结构
385
+ structure = [
386
+ f"{project_name}/README.md",
387
+ f"{project_name}/requirements.txt",
388
+ f"{project_name}/{project_name}/",
389
+ f"{project_name}/{project_name}/__init__.py",
390
+ f"{project_name}/{project_name}/main.py",
391
+ f"{project_name}/setup.py",
392
+ ]
393
+
394
+ for path in structure:
395
+ if path.endswith('/'):
396
+ self.remote_host.run(f"mkdir -p {path}", use_cache=use_cache)
397
+ else:
398
+ self.remote_host.run(f"touch {path}", use_cache=use_cache)
399
+
400
+ # 写入基本内容
401
+ self.remote_host.run(f"echo '# {project_name}' > {project_name}/README.md", use_cache=use_cache)
402
+ self.remote_host.run(f"echo '"""{project_name} package"""\n\n__version__ = "0.1.0"' > {project_name}/{project_name}/__init__.py", use_cache=use_cache)
403
+ self.remote_host.run(f"echo 'def main():\n print(\"Hello from {project_name}!")' > {project_name}/{project_name}/main.py", use_cache=use_cache)
404
+
405
+ elif template == 'flask':
406
+ # 创建Flask项目
407
+ self.install_python_package('Flask', use_cache=use_cache)
408
+ self.remote_host.run(f"echo 'from flask import Flask\n\napp = Flask(__name__)\n\n@app.route(\"/\")\ndef hello():\n return \"Hello, World!\"\n\nif __name__ == \"__main__\":\n app.run(debug=True)' > {project_name}/app.py", use_cache=use_cache)
409
+ self.remote_host.run(f"echo 'Flask' > {project_name}/requirements.txt", use_cache=use_cache)
410
+
411
+ elif template == 'django':
412
+ # 创建Django项目
413
+ self.install_python_package('Django', use_cache=use_cache)
414
+ self.remote_host.run(f"cd {project_name} && django-admin startproject {project_name} .", use_cache=use_cache)
415
+
416
+ elif template == 'fastapi':
417
+ # 创建FastAPI项目
418
+ self.install_python_package('fastapi', use_cache=use_cache)
419
+ self.install_python_package('uvicorn', use_cache=use_cache)
420
+ self.remote_host.run(f"echo 'from fastapi import FastAPI\n\napp = FastAPI()\n\n@app.get(\"/\")\nasync def root():\n return {\"message\": \"Hello World\"}' > {project_name}/app.py", use_cache=use_cache)
421
+ self.remote_host.run(f"echo 'fastapi\nuvicorn' > {project_name}/requirements.txt", use_cache=use_cache)
422
+
423
+ print(f"✅ 项目 '{project_name}' 创建完成")
424
+ return f"项目 '{project_name}' 已创建,使用模板: {template}"
425
+
426
+
427
+ def get_remote_tools(remote_host) -> RemoteTools:
428
+ """
429
+ 获取远程工具实例
430
+
431
+ Args:
432
+ remote_host: RemoteHost实例
433
+ """
434
+ return RemoteTools(remote_host)