AutoCython-zhang 2.2.0__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.
@@ -0,0 +1,36 @@
1
+ import os
2
+ from .run_tasks import run_tasks
3
+ from .compile import compile_to_binary
4
+ from .tools import parse_arguments, find_python_files
5
+ from .tools import show_no_compilable_files, show_file_not_found, show_path_not_found
6
+
7
+ def compile():
8
+ args = parse_arguments()
9
+
10
+ if args.file:
11
+ if os.path.isfile(args.file):
12
+ compile_file = args.file
13
+ del_source = args.del_source
14
+ tasks = [
15
+ # 函数, 位置参数, 关键字参数
16
+ (compile_to_binary, compile_file, (compile_file, del_source), {}),
17
+ ]
18
+ run_tasks(tasks, max_workers=1) # 执行编译
19
+ else:
20
+ show_file_not_found(args.file)
21
+ elif args.path:
22
+ if os.path.exists(args.path) and not os.path.isfile(args.path):
23
+ compile_file_list = find_python_files(args.path)
24
+ if compile_file_list:
25
+ del_source = args.del_source
26
+ tasks = []
27
+ for compile_file in compile_file_list:
28
+ tasks.append(
29
+ # 函数, 位置参数, 关键字参数
30
+ (compile_to_binary, compile_file, (compile_file, del_source), {}),
31
+ )
32
+ run_tasks(tasks, max_workers=args.conc) # 执行编译
33
+ else:
34
+ show_no_compilable_files(args.path)
35
+ else:
36
+ show_path_not_found(args.path)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ from ._version import __version__
4
+ from .AutoCython import compile
5
+
6
+
7
+ def main():
8
+ compile()
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """版本号模块,从 pyproject.toml 中读取版本号"""
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ # Python 3.11+ 使用内置 tomllib,否则使用 tomli
8
+ if sys.version_info >= (3, 11):
9
+ import tomllib
10
+ else:
11
+ try:
12
+ import tomli as tomllib
13
+ except ImportError:
14
+ tomllib = None
15
+
16
+
17
+ def _get_version() -> str:
18
+ """从 pyproject.toml 中获取版本号"""
19
+ if tomllib is None:
20
+ return "0.0.0"
21
+ toml_path = Path(__file__).parent.parent / "pyproject.toml"
22
+ if toml_path.exists():
23
+ with open(toml_path, "rb") as f:
24
+ data = tomllib.load(f)
25
+ return data.get("project", {}).get("version", "0.0.0")
26
+ return "0.0.0"
27
+
28
+
29
+ __version__ = _get_version()
@@ -0,0 +1,140 @@
1
+ import os
2
+ import sys
3
+ import glob
4
+ import shutil
5
+ import tempfile
6
+ import subprocess
7
+
8
+ def get_platform_extension() -> str:
9
+ """返回当前平台的扩展名"""
10
+ if sys.platform.startswith('win'):
11
+ return '.pyd'
12
+ return '.so'
13
+
14
+ def compile_to_binary(file_path: str, del_source=False):
15
+ """
16
+ 将指定的 Python 文件(.py)通过 Cython 编译为二进制扩展文件
17
+
18
+ :param file_path: Python 文件路径(可以是相对路径或绝对路径)
19
+ :param del_source: 是否删除源代码
20
+ :return: 生成的二进制文件路径(与输入保持相同的路径类型)
21
+ """
22
+ # 保存原始路径类型(相对/绝对)
23
+ is_absolute = os.path.isabs(file_path)
24
+
25
+ # 获取绝对路径用于内部操作
26
+ abs_file_path = os.path.abspath(file_path)
27
+
28
+ if not os.path.isfile(abs_file_path):
29
+ raise FileNotFoundError(f"FileNotFoundError: {file_path}.")
30
+
31
+ # 获取文件名和目录
32
+ file_name = os.path.basename(abs_file_path)
33
+ module_name, ext = os.path.splitext(file_name)
34
+ source_dir = os.path.dirname(abs_file_path) # 源文件所在目录(绝对路径)
35
+
36
+ if ext != ".py":
37
+ raise ValueError(f"ValueError: The file {file_path} is not a valid Python file (.py)!")
38
+
39
+ # 获取平台特定扩展名
40
+ target_ext = get_platform_extension()
41
+
42
+ # 创建临时工作目录
43
+ temp_dir = tempfile.mkdtemp()
44
+
45
+ try:
46
+ # 将目标文件复制到临时目录
47
+ temp_file_path = os.path.join(temp_dir, file_name)
48
+ shutil.copy2(abs_file_path, temp_file_path)
49
+
50
+ # 创建临时的 setup.py 文件
51
+ setup_code = f"""
52
+ from setuptools import setup
53
+ from Cython.Build import cythonize
54
+
55
+ # 编译器指令
56
+ compiler_directives = {{
57
+ 'language_level': '3',
58
+ 'annotation_typing': False,
59
+ 'always_allow_keywords': True,
60
+ 'binding': True,
61
+ 'embedsignature': True,
62
+ 'wraparound': False,
63
+ }}
64
+
65
+ setup(
66
+ ext_modules=cythonize(
67
+ {repr(file_name)},
68
+ compiler_directives=compiler_directives,
69
+ force=True
70
+ )
71
+ )
72
+ """
73
+ setup_path = os.path.join(temp_dir, "setup.py")
74
+ with open(setup_path, "w", encoding='utf-8') as f:
75
+ f.write(setup_code)
76
+
77
+ # 执行编译命令
78
+ command = [sys.executable, "setup.py", "build_ext", "--inplace"]
79
+ result = subprocess.run(
80
+ command,
81
+ cwd=temp_dir,
82
+ stdout=subprocess.PIPE,
83
+ stderr=subprocess.PIPE
84
+ )
85
+
86
+ if result.returncode != 0:
87
+ error_msg = result.stderr.decode('utf-8', errors='replace')
88
+ raise RuntimeError(f"Compilation failed: {error_msg}")
89
+
90
+ # 查找生成的二进制文件
91
+ pattern = os.path.join(temp_dir, f"{module_name}*{target_ext}")
92
+ matches = glob.glob(pattern)
93
+
94
+ if not matches:
95
+ pattern = os.path.join(temp_dir, f"*{module_name}*{target_ext}")
96
+ matches = glob.glob(pattern)
97
+
98
+ if not matches:
99
+ raise FileNotFoundError(f"FileNotFoundError: The file {file_path} is not a valid Python file (.py)! Generated file {target_ext} not found, in {temp_dir} possible file: {os.listdir(temp_dir)}")
100
+
101
+ # 取最新生成的文件
102
+ generated_file = max(matches, key=os.path.getctime)
103
+
104
+ # 获取源文件的目录(使用原始路径类型)
105
+ if is_absolute:
106
+ output_dir = source_dir
107
+ else:
108
+ # 如果输入是相对路径,保持相对路径
109
+ output_dir = os.path.dirname(file_path) or '.'
110
+
111
+ # 创建目标目录(如果不存在)
112
+ if output_dir and not os.path.exists(output_dir):
113
+ os.makedirs(output_dir, exist_ok=True)
114
+
115
+ # 目标文件路径(保持原始路径类型)
116
+ output_file_name = os.path.basename(generated_file)
117
+ output_path = os.path.join(output_dir, output_file_name)
118
+
119
+ # 移动文件
120
+ shutil.move(generated_file, output_path)
121
+
122
+ if del_source:
123
+ os.remove(file_path)
124
+
125
+ # 返回与输入相同类型的路径
126
+ return output_path
127
+ finally:
128
+ # 清理临时目录
129
+ shutil.rmtree(temp_dir, ignore_errors=True)
130
+
131
+ # 测试函数
132
+ if __name__ == "__main__":
133
+ # 替换为你的 Python 文件路径
134
+ target_file = "test/example.py" # 请确保文件路径正确
135
+
136
+ try:
137
+ output_file = compile_to_binary(target_file)
138
+ print(output_file)
139
+ except Exception as e:
140
+ print(e)
@@ -0,0 +1,301 @@
1
+ import os
2
+ import time
3
+ import locale
4
+ import platform
5
+ import threading
6
+ import concurrent.futures
7
+ from rich.live import Live
8
+ from rich.text import Text
9
+ from rich.table import Table
10
+ from rich.console import Console
11
+ from rich.spinner import Spinner
12
+ from rich.columns import Columns
13
+ from rich.progress import Progress, BarColumn, TimeRemainingColumn, TimeElapsedColumn
14
+
15
+ def get_system_language():
16
+ """
17
+ 获取系统语言,兼容 Python 3.11+
18
+
19
+ :return: 'zh' 或 'en'
20
+ """
21
+ try:
22
+ # Python 3.11+ 推荐方式
23
+ lang = locale.getlocale()[0]
24
+ if lang is None:
25
+ # 回退到环境变量
26
+ lang = os.environ.get('LANG', os.environ.get('LANGUAGE', ''))
27
+ return 'zh' if lang and lang.startswith('zh') else 'en'
28
+ except Exception:
29
+ return 'en'
30
+
31
+ def run_tasks(task_list, max_workers=2, language=None):
32
+ """
33
+ 并发执行任务列表并实时显示状态
34
+
35
+ :param task_list: 任务列表,每个元素是 (函数, 位置参数元组, 关键字参数字典)
36
+ :param max_workers: 最大并发线程数
37
+ :param language: 显示语言 ('en' 或 'zh', 默认根据系统语言自动判断)
38
+ """
39
+ print("""\n █████╗ ██╗ ██╗████████╗ ██████╗ ██████╗██╗ ██╗████████╗██╗ ██╗ ██████╗ ███╗ ██╗
40
+ ██╔══██╗██║ ██║╚══██╔══╝██╔═══██╗██╔════╝╚██╗ ██╔╝╚══██╔══╝██║ ██║██╔═══██╗████╗ ██║
41
+ ███████║██║ ██║ ██║ ██║ ██║██║ ╚████╔╝ ██║ ███████║██║ ██║██╔██╗ ██║
42
+ ██╔══██║██║ ██║ ██║ ██║ ██║██║ ╚██╔╝ ██║ ██╔══██║██║ ██║██║╚██╗██║
43
+ ██║ ██║╚██████╔╝ ██║ ╚██████╔╝╚██████╗ ██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║
44
+ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝""")
45
+
46
+ bit_architecture = platform.architecture()[0] # 获取位数信息,例如 '64bit' 或 '32bit'
47
+ print(f"{platform.system()} {platform.version()} {platform.machine()} | {platform.python_implementation()} {platform.python_version()} {platform.python_compiler()} | {bit_architecture}")
48
+
49
+ # 获取系统默认区域设置
50
+ language = get_system_language()
51
+
52
+ # 中英文文本映射
53
+ TEXT_MAP = {
54
+ 'en': {
55
+ 'overall_progress': "[cyan]Overall Progress",
56
+ 'total_tasks': "\n📊 Total Tasks: ",
57
+ 'completed': " ✅ Completed: ",
58
+ 'elapsed': " ⏱️ Elapsed Time: ",
59
+ 'remaining': " ⏳ Estimated Remaining: ",
60
+ 'id': "ID",
61
+ 'status': "Status",
62
+ 'function': "Names",
63
+ 'time': "Time (s)",
64
+ 'result': "Result",
65
+ 'status_pending': "⏱️ Pending",
66
+ 'status_running': " Compiling",
67
+ 'status_success': "✅ Success",
68
+ 'status_failed': "❌ Failed",
69
+ 'succeeded': "\n[bold green]✅ Tasks succeeded: {0}[/bold green] |",
70
+ 'failed': " [bold red]❌ Tasks failed: {0}[/bold red] |",
71
+ 'total_time': " [bold]⏱️ Total time: [bold green]{0:.2f}s[/bold green][/bold] |",
72
+ 'all_completed': " [bold green]🎉 All compilation tasks completed![/bold green]",
73
+ 'wait_test': "Waiting for the test...",
74
+ },
75
+ 'zh': {
76
+ 'overall_progress': "[cyan]总进度",
77
+ 'total_tasks': "\n📊 总任务数: ",
78
+ 'completed': " ✅ 已完成: ",
79
+ 'elapsed': " ⏱️ 已用时间: ",
80
+ 'remaining': " ⏳ 预计剩余: ",
81
+ 'id': "ID",
82
+ 'status': "状态",
83
+ 'function': "名称",
84
+ 'time': "时间 (秒)",
85
+ 'result': "结果",
86
+ 'status_pending': "⏱️ 等待编译",
87
+ 'status_running': " 编译中",
88
+ 'status_success': "✅ 编译成功",
89
+ 'status_failed': "❌ 编译失败",
90
+ 'succeeded': "\n[bold green]✅ 成功任务数: {0}[/bold green] |",
91
+ 'failed': " [bold red]❌ 失败任务数: {0}[/bold red] |",
92
+ 'total_time': " [bold]⏱️ 总耗时: [bold green]{0:.2f}s[/bold green][/bold] |",
93
+ 'all_completed': " [bold green]🎉 所有编译任务已完成![/bold green]",
94
+ 'wait_test': "等待测试..",
95
+ }
96
+ }
97
+ # 获取当前语言文本
98
+ t = TEXT_MAP.get(language, TEXT_MAP['en'])
99
+
100
+ console = Console()
101
+ start_time = time.time()
102
+ completed = 0
103
+ completed_lock = threading.Lock() # 保护 completed 变量的锁
104
+ total_tasks = len(task_list)
105
+
106
+ # 创建任务状态数据
107
+ task_status = [
108
+ {
109
+ "id": idx,
110
+ "func": func,
111
+ "name": name,
112
+ "args": args,
113
+ "kwargs": kwargs,
114
+ "status": "pending",
115
+ "start": None,
116
+ "end": None,
117
+ "result": None,
118
+ "error": None,
119
+ "lock": threading.Lock() # 添加锁保证线程安全
120
+ }
121
+ for idx, (func, name, args, kwargs) in enumerate(task_list, 1)
122
+ ]
123
+
124
+ # 创建进度条
125
+ progress = Progress(
126
+ "[progress.description]{task.description}",
127
+ BarColumn(bar_width=60),
128
+ "[progress.percentage]{task.percentage:>3.0f}%",
129
+ TimeRemainingColumn(),
130
+ TimeElapsedColumn(),
131
+ console=console
132
+ )
133
+ overall_task = progress.add_task(t['overall_progress'], total=total_tasks)
134
+
135
+ # 用于控制实时更新的标志
136
+ refresh_event = threading.Event()
137
+
138
+ def execute_task(task):
139
+ """执行单个任务并记录结果"""
140
+ with task["lock"]:
141
+ task["status"] = "running"
142
+ task["start"] = time.time()
143
+ refresh_event.set() # 触发刷新
144
+
145
+ try:
146
+ result = task["func"](*task["args"], **task["kwargs"])
147
+ with task["lock"]:
148
+ task["status"] = "success"
149
+ task["result"] = result
150
+ except Exception as e:
151
+ with task["lock"]:
152
+ task["status"] = "failed"
153
+ task["error"] = str(e)
154
+ finally:
155
+ with task["lock"]:
156
+ task["end"] = time.time()
157
+ refresh_event.set() # 触发刷新
158
+
159
+ nonlocal completed
160
+ with completed_lock:
161
+ completed += 1
162
+ progress.update(overall_task, advance=1)
163
+ refresh_event.set() # 触发刷新
164
+ return task
165
+
166
+ def generate_display():
167
+ """生成实时显示内容"""
168
+ # 创建总状态面板
169
+ total_panel = Table.grid(padding=1)
170
+ elapsed_time = time.time() - start_time
171
+ if completed > 0 and completed < total_tasks:
172
+ remaining_time = (elapsed_time / completed) * (total_tasks - completed)
173
+ total_panel.add_row(
174
+ Text(t['total_tasks'], style="bold") + Text(f"{total_tasks}", style="bold cyan") + Text(" |") +
175
+ Text(t['completed'], style="bold") + Text(f"{completed}/{total_tasks}", style="bold cyan") + Text(" |") +
176
+ Text(t['elapsed'], style="bold") + Text(f"{elapsed_time:.2f}s", style="bold green") + Text(" |") +
177
+ Text(t['remaining'], style="bold") + Text(f"{remaining_time:.2f}s\n", style="bold yellow")
178
+ )
179
+ elif completed >= total_tasks:
180
+ total_panel.add_row(
181
+ Text(t['total_tasks'], style="bold") + Text(f"{total_tasks}", style="bold cyan") + Text(" |") +
182
+ Text(t['completed'], style="bold") + Text(f"{completed}/{total_tasks}", style="bold cyan") + Text(" |") +
183
+ Text(t['elapsed'], style="bold") + Text(f"{elapsed_time:.2f}s", style="bold green") + Text(" |") +
184
+ Text(t['remaining'], style="bold") + Text("0.00s\n", style="bold yellow")
185
+ )
186
+ else:
187
+ total_panel.add_row(
188
+ Text(t['total_tasks'], style="bold") + Text(f"{total_tasks}", style="bold cyan") + Text(" |") +
189
+ Text(t['completed'], style="bold") + Text(f"{completed}/{total_tasks}", style="bold cyan") + Text(" |") +
190
+ Text(t['elapsed'], style="bold") + Text(f"{elapsed_time:.2f}s", style="bold green") + Text(" |") +
191
+ Text(t['remaining'], style="bold") + Text(f"{t['wait_test']}\n", style="bold yellow")
192
+ )
193
+
194
+ # 创建任务表格
195
+ table = Table(show_header=True, header_style="bold magenta", box=None)
196
+ table.add_column(t['id'], width=5, justify="center")
197
+ table.add_column(t['status'], width=15)
198
+ table.add_column(t['function'], width=30)
199
+ table.add_column(t['time'], width=10, justify="right")
200
+ table.add_column(t['result'], width=80)
201
+
202
+ # 添加任务行
203
+ for task in task_status:
204
+ with task["lock"]: # 使用锁保证状态一致性
205
+ # 计算运行时间
206
+ run_time = (
207
+ (task["end"] or time.time()) - task["start"]
208
+ if task["start"] else 0
209
+ )
210
+
211
+ # 状态显示
212
+ if task["status"] == "pending":
213
+ status = Text(t['status_pending'], style="yellow")
214
+ result_text = Text("-")
215
+ elif task["status"] == "running":
216
+ # 使用Columns组合Spinner和Text
217
+ spinner = Spinner("dots", style="blue")
218
+ status = Columns([spinner, Text(t['status_running'], style="blue")])
219
+ result_text = Text("-")
220
+ elif task["status"] == "success":
221
+ status = Text(t['status_success'], style="green bold")
222
+ result_text = Text(str(task["result"]), style="green")
223
+ else: # failed
224
+ status = Text(t['status_failed'], style="red bold")
225
+ result_text = Text(task["error"], style="red")
226
+
227
+ table.add_row(
228
+ str(task["id"]),
229
+ status,
230
+ task["name"],
231
+ f"{run_time:.3f}",
232
+ result_text
233
+ )
234
+
235
+ # 组合所有元素
236
+ group = Table.grid()
237
+ group.add_row(table)
238
+ group.add_row(total_panel)
239
+ group.add_row(progress)
240
+
241
+ return group
242
+
243
+ # 使用Live上下文管理器实现实时刷新
244
+ with Live(console=console, refresh_per_second=20, vertical_overflow="visible") as live:
245
+ with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
246
+ # 提交所有任务
247
+ futures = {executor.submit(execute_task, task): task for task in task_status}
248
+
249
+ # 初始显示
250
+ live.update(generate_display())
251
+
252
+ # 实时更新显示(使用事件驱动刷新)
253
+ last_refresh_time = time.time()
254
+ while completed < total_tasks:
255
+ # 定期刷新或状态变化时刷新
256
+ if refresh_event.is_set() or (time.time() - last_refresh_time) > 0.05:
257
+ live.update(generate_display())
258
+ refresh_event.clear()
259
+ last_refresh_time = time.time()
260
+ time.sleep(0.01)
261
+
262
+ # 等待所有任务完成
263
+ concurrent.futures.wait(futures)
264
+
265
+ # 最终显示
266
+ live.update(generate_display())
267
+
268
+ # 最终汇总信息
269
+ total_elapsed = time.time() - start_time
270
+ success_count = sum(1 for t in task_status if t["status"] == "success")
271
+ failure_count = sum(1 for t in task_status if t["status"] == "failed")
272
+
273
+ console.print(t['succeeded'].format(success_count) + t['failed'].format(failure_count) + t['total_time'].format(total_elapsed) + t['all_completed'])
274
+
275
+ # 示例使用方式
276
+ if __name__ == "__main__":
277
+ # 示例任务函数
278
+ def task_success(seconds):
279
+ time.sleep(seconds)
280
+ return f"Slept for {seconds}s"
281
+
282
+ def task_failure():
283
+ time.sleep(0.5)
284
+ raise ValueError("Intentional error")
285
+
286
+ def long_task(seconds):
287
+ time.sleep(seconds)
288
+ return f"Long task {seconds}s"
289
+
290
+ # 创建任务列表 (函数, 位置参数, 关键字参数)
291
+ tasks = [
292
+ (task_success, task_success.__name__, (0.5,), {}),
293
+ (task_failure, task_failure.__name__, (), {}),
294
+ (long_task, long_task.__name__, (2.5,), {}),
295
+ (task_success, task_success.__name__, (1.2,), {}),
296
+ (long_task, long_task.__name__, (1.8,), {}),
297
+ (task_failure, task_failure.__name__, (), {}),
298
+ ]
299
+
300
+ # 执行任务 (最大并发4个)
301
+ run_tasks(tasks, max_workers=2, language='en')
@@ -0,0 +1,178 @@
1
+ import os
2
+ import sys
3
+ import locale
4
+ import argparse
5
+
6
+ from ._version import __version__
7
+
8
+ def get_system_language():
9
+ """
10
+ 获取系统语言,兼容 Python 3.11+
11
+
12
+ :return: 'zh' 或 'en'
13
+ """
14
+ try:
15
+ # Python 3.11+ 推荐方式
16
+ lang = locale.getlocale()[0]
17
+ if lang is None:
18
+ # 回退到环境变量
19
+ lang = os.environ.get('LANG', os.environ.get('LANGUAGE', ''))
20
+ return 'zh' if lang and lang.startswith('zh') else 'en'
21
+ except Exception:
22
+ return 'en'
23
+
24
+ def find_python_files(path):
25
+ """
26
+ 查找指定路径下的所有子孙py文件,不包括 __init__.py, 排除头两行包含"# AutoCython No Compile"的文件
27
+
28
+ :param path: 要搜索的根目录路径
29
+ :return: 符合条件的py文件路径列表
30
+ """
31
+ # 排除标记(兼容旧版本拼写错误)
32
+ exclude_markers = ["# AutoCython No Compile", "# AucoCython No Compile"]
33
+
34
+ def has_exclude_marker(line):
35
+ return any(marker in line for marker in exclude_markers)
36
+
37
+ valid_py_files = []
38
+
39
+ for root, dirs, files in os.walk(path):
40
+ for file in files:
41
+ if file == "__init__.py":
42
+ continue
43
+ if file.endswith('.py'):
44
+ filepath = os.path.join(root, file)
45
+
46
+ try:
47
+ with open(filepath, 'r', encoding='utf-8') as f:
48
+ # 读取头两行
49
+ line1 = f.readline()
50
+ line2 = f.readline()
51
+
52
+ # 检查是否包含排除标记
53
+ if not has_exclude_marker(line1) and not has_exclude_marker(line2):
54
+ valid_py_files.append(filepath)
55
+ except UnicodeDecodeError:
56
+ # 如果utf-8解码失败,尝试其他编码
57
+ try:
58
+ with open(filepath, 'r', encoding='latin-1') as f:
59
+ line1 = f.readline()
60
+ line2 = f.readline()
61
+
62
+ if not has_exclude_marker(line1) and not has_exclude_marker(line2):
63
+ valid_py_files.append(filepath)
64
+ except Exception as e:
65
+ print(f"无法读取文件 {filepath}: {e}")
66
+ except Exception as e:
67
+ print(f"处理文件 {filepath} 时出错: {e}")
68
+
69
+ return valid_py_files
70
+
71
+ def parse_arguments():
72
+ # 获取系统语言
73
+ lang = get_system_language()
74
+
75
+ # 中英文帮助信息配置
76
+ help_messages = {
77
+ 'en': {
78
+ 'description': 'AutoCython',
79
+ 'file_help': 'Compile File Path',
80
+ 'path_help': 'Compile directory path',
81
+ 'conc_help': 'Compile concurrency count (default: 2)',
82
+ 'del_help': 'Remove source code after compilation (default: False)',
83
+ 'help_help': 'Show help message',
84
+ 'version_help': 'Show program version',
85
+ 'version_text': f'v{__version__}',
86
+ 'required_error': 'The following arguments are required: {}',
87
+ 'epilog': 'Example:\n AutoCython -f demo.py\n AutoCython -p path'
88
+ },
89
+ 'zh': {
90
+ 'description': 'AutoCython',
91
+ 'file_help': '编译文件路径',
92
+ 'path_help': '编译目录路径',
93
+ 'conc_help': '编译并发数(默认:2)',
94
+ 'del_help': '编译后删除源代码(默认:False)',
95
+ 'help_help': '显示帮助信息',
96
+ 'version_help': '显示程序版本',
97
+ 'version_text': f'v{__version__}',
98
+ 'required_error': '缺少必要参数: {}',
99
+ 'epilog': '示例:\n AutoCython -f demo.py\n AutoCython -p path'
100
+ }
101
+ }
102
+ msg = help_messages[lang]
103
+
104
+ # 创建带自定义错误处理的解析器
105
+ class CustomParser(argparse.ArgumentParser):
106
+ def error(self, message):
107
+ self.print_usage(sys.stderr)
108
+ required_args = [f'--{a.dest}' for a in self._actions if a.required]
109
+ err_msg = msg['required_error'].format(', '.join(required_args))
110
+ sys.stderr.write(f'error: {err_msg}\n')
111
+ sys.exit(2)
112
+
113
+ # 配置参数解析器
114
+ parser = CustomParser(
115
+ description=msg['description'],
116
+ epilog=msg['epilog'],
117
+ add_help=False,
118
+ formatter_class=argparse.RawTextHelpFormatter
119
+ )
120
+
121
+ # 添加参数定义
122
+ required_group = parser.add_argument_group('required arguments')
123
+ required_group.add_argument('-f', '--file', type=str, help=msg['file_help'])
124
+ required_group.add_argument('-p', '--path', type=str, help=msg['path_help'])
125
+
126
+ optional_group = parser.add_argument_group('optional arguments')
127
+ optional_group.add_argument('-c', '--conc', type=int, default=2, help=msg['conc_help'])
128
+ optional_group.add_argument('-d', '--del', dest='del_source', action='store_true', help=msg['del_help'])
129
+ optional_group.add_argument('-h', '--help', action='store_true', help=msg['help_help'])
130
+ optional_group.add_argument('-v', '--version', action='store_true', help=msg['version_help'])
131
+
132
+ # 解析参数
133
+ args = parser.parse_args()
134
+
135
+ # 处理帮助和版本请求
136
+ if args.help:
137
+ parser.print_help()
138
+ sys.exit(0)
139
+
140
+ if args.version:
141
+ print(msg['version_text'])
142
+ sys.exit(0)
143
+
144
+ if not args.file and not args.path:
145
+ parser.print_help()
146
+ sys.exit(0)
147
+
148
+ return args
149
+
150
+ def show_no_compilable_files(path):
151
+ lang = get_system_language()
152
+
153
+ if lang == 'zh':
154
+ print(f"{path} 目录下没有任何需要编译的文件!")
155
+ else:
156
+ print(f"The {path} directory does not contain any files that need to be compiled!")
157
+
158
+ def show_file_not_found(file):
159
+ lang = get_system_language()
160
+
161
+ if lang == 'zh':
162
+ print(f"文件 {file} 不存在!")
163
+ else:
164
+ print(f"File {file} does not exist!")
165
+
166
+ def show_path_not_found(path):
167
+ lang = get_system_language()
168
+
169
+ if lang == 'zh':
170
+ print(f"路径 {path} 不存在!")
171
+ else:
172
+ print(f"Path {path} does not exist!")
173
+
174
+ if __name__ == "__main__":
175
+ args = parse_arguments()
176
+ print(f"文件: {args.file}")
177
+ print(f"路径: {args.path}")
178
+ print(f"并发数: {args.conc}")
@@ -0,0 +1,109 @@
1
+ Metadata-Version: 2.4
2
+ Name: AutoCython-zhang
3
+ Version: 2.2.0
4
+ Summary: 自动Cython,使用Cython批量编译.py文件为.pyd文件!
5
+ Author-email: zhang_gavin <qq814608@163.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) [2024] [JianJun]
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: homepage, https://github.com/zhang0281/AutoCython
29
+ Project-URL: repository, https://github.com/zhang0281/AutoCython
30
+ Project-URL: documentation, https://github.com/zhang0281/AutoCython#readme
31
+ Keywords: cython,compile,pyd,pyc,python,autopyd
32
+ Classifier: Programming Language :: Python :: 3
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Operating System :: OS Independent
35
+ Description-Content-Type: text/markdown
36
+ License-File: LICENSE
37
+ Requires-Dist: setuptools
38
+ Requires-Dist: cython
39
+ Requires-Dist: rich
40
+ Requires-Dist: tomli; python_version < "3.11"
41
+ Dynamic: license-file
42
+
43
+ # AutoCython V2
44
+ 中文 | [English](https://github.com/EVA-JianJun/AutoCython/blob/master/README.en.md)
45
+
46
+ **自动 Cython:一键将 Python 文件批量编译为 `PYD / SO` 文件**
47
+ ![py_pyd](https://raw.githubusercontent.com/EVA-JianJun/GitPigBed/master/blog_files/img/AutoCython_20250623.png)
48
+
49
+ ## ✨ 特性
50
+ - 单文件/多文件批量编译
51
+ - 跨平台支持 (Windows/Linux/MacOS)
52
+ - 简洁命令行界面
53
+
54
+ ## 📦 安装
55
+ ```bash
56
+ pip install -U AutoCython-jianjun
57
+ ```
58
+
59
+ ## ⚙️ 依赖环境
60
+ ### C/C++ 编译器
61
+ - **Windows**: Visual Studio
62
+ - **Linux**: gcc & g++
63
+
64
+ **重要提示**:编译器架构必须与Python解释器一致(64位Python需64位编译器)
65
+
66
+ > 其他编译器配置请参考 [Cython](https://github.com/cython/cython) 项目
67
+
68
+ ## 🚀 使用指南
69
+ ### 命令行操作
70
+ ![命令行演示](https://raw.githubusercontent.com/EVA-JianJun/GitPigBed/master/blog_files/img/AutoCython_20250609_1.png)
71
+
72
+ ```bash
73
+ # 编译单个文件
74
+ AutoCython -f test.py
75
+
76
+ # 编译整个目录
77
+ AutoCython -p D:/python_code/ProjectPath
78
+
79
+ # 编译后删除源代码 (默认不删除)
80
+ AutoCython -d True -f test.py
81
+ AutoCython -d True -p D:/python_code/ProjectPath
82
+ ```
83
+
84
+ ### 编译界面
85
+ ![AutoCython GUI](https://raw.githubusercontent.com/EVA-JianJun/GitPigBed/master/blog_files/img/AutoCython_20250609_2.png)
86
+
87
+ ### 手动排除文件不编译
88
+ 在文件头部 **前两行** 添加声明:
89
+ ```python
90
+ # AutoCython No Compile
91
+ # 此文件将跳过编译处理
92
+ ```
93
+
94
+ ## ⚠️ 常见问题解决
95
+
96
+ 一般是源代码中有 Cython 不支持的语句, 或者文件名不支持等.
97
+ 可以查阅 [Cython Wiki](https://github.com/cython/cython/wiki) 项目 官方文档, 或者提 Issue.
98
+
99
+ ## 📅 更新记录
100
+ ### V2 版本
101
+ 1. 20250623 release V2.1.0 禁用激进的性能优化选项. 显示系统信息.
102
+ 2. 20250609 release V2.0.0 重构了代码, 使用新的界面 (不安全版本)
103
+
104
+ ### V1 版本
105
+ 1. 20220613 更新对Linux的支持, Linux下需要配置gcc&g++
106
+ 2. 20221123 可以通过文件头手动指定不编译的文件
107
+ 3. 20230306 更新可以指定命令行头如 `Python310` 以此支持非Widnows系统下编译
108
+ 4. 20230324 更新文档
109
+ 5. 20240506 修复编译失败时遗漏复原 \_\_init\_\_.py 的问题
@@ -0,0 +1,15 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ AutoCython/AutoCython.py
5
+ AutoCython/__init__.py
6
+ AutoCython/_version.py
7
+ AutoCython/compile.py
8
+ AutoCython/run_tasks.py
9
+ AutoCython/tools.py
10
+ AutoCython_zhang.egg-info/PKG-INFO
11
+ AutoCython_zhang.egg-info/SOURCES.txt
12
+ AutoCython_zhang.egg-info/dependency_links.txt
13
+ AutoCython_zhang.egg-info/entry_points.txt
14
+ AutoCython_zhang.egg-info/requires.txt
15
+ AutoCython_zhang.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ AutoCython = AutoCython:main
@@ -0,0 +1,6 @@
1
+ setuptools
2
+ cython
3
+ rich
4
+
5
+ [:python_version < "3.11"]
6
+ tomli
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [2024] [JianJun]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,109 @@
1
+ Metadata-Version: 2.4
2
+ Name: AutoCython-zhang
3
+ Version: 2.2.0
4
+ Summary: 自动Cython,使用Cython批量编译.py文件为.pyd文件!
5
+ Author-email: zhang_gavin <qq814608@163.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) [2024] [JianJun]
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: homepage, https://github.com/zhang0281/AutoCython
29
+ Project-URL: repository, https://github.com/zhang0281/AutoCython
30
+ Project-URL: documentation, https://github.com/zhang0281/AutoCython#readme
31
+ Keywords: cython,compile,pyd,pyc,python,autopyd
32
+ Classifier: Programming Language :: Python :: 3
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Operating System :: OS Independent
35
+ Description-Content-Type: text/markdown
36
+ License-File: LICENSE
37
+ Requires-Dist: setuptools
38
+ Requires-Dist: cython
39
+ Requires-Dist: rich
40
+ Requires-Dist: tomli; python_version < "3.11"
41
+ Dynamic: license-file
42
+
43
+ # AutoCython V2
44
+ 中文 | [English](https://github.com/EVA-JianJun/AutoCython/blob/master/README.en.md)
45
+
46
+ **自动 Cython:一键将 Python 文件批量编译为 `PYD / SO` 文件**
47
+ ![py_pyd](https://raw.githubusercontent.com/EVA-JianJun/GitPigBed/master/blog_files/img/AutoCython_20250623.png)
48
+
49
+ ## ✨ 特性
50
+ - 单文件/多文件批量编译
51
+ - 跨平台支持 (Windows/Linux/MacOS)
52
+ - 简洁命令行界面
53
+
54
+ ## 📦 安装
55
+ ```bash
56
+ pip install -U AutoCython-jianjun
57
+ ```
58
+
59
+ ## ⚙️ 依赖环境
60
+ ### C/C++ 编译器
61
+ - **Windows**: Visual Studio
62
+ - **Linux**: gcc & g++
63
+
64
+ **重要提示**:编译器架构必须与Python解释器一致(64位Python需64位编译器)
65
+
66
+ > 其他编译器配置请参考 [Cython](https://github.com/cython/cython) 项目
67
+
68
+ ## 🚀 使用指南
69
+ ### 命令行操作
70
+ ![命令行演示](https://raw.githubusercontent.com/EVA-JianJun/GitPigBed/master/blog_files/img/AutoCython_20250609_1.png)
71
+
72
+ ```bash
73
+ # 编译单个文件
74
+ AutoCython -f test.py
75
+
76
+ # 编译整个目录
77
+ AutoCython -p D:/python_code/ProjectPath
78
+
79
+ # 编译后删除源代码 (默认不删除)
80
+ AutoCython -d True -f test.py
81
+ AutoCython -d True -p D:/python_code/ProjectPath
82
+ ```
83
+
84
+ ### 编译界面
85
+ ![AutoCython GUI](https://raw.githubusercontent.com/EVA-JianJun/GitPigBed/master/blog_files/img/AutoCython_20250609_2.png)
86
+
87
+ ### 手动排除文件不编译
88
+ 在文件头部 **前两行** 添加声明:
89
+ ```python
90
+ # AutoCython No Compile
91
+ # 此文件将跳过编译处理
92
+ ```
93
+
94
+ ## ⚠️ 常见问题解决
95
+
96
+ 一般是源代码中有 Cython 不支持的语句, 或者文件名不支持等.
97
+ 可以查阅 [Cython Wiki](https://github.com/cython/cython/wiki) 项目 官方文档, 或者提 Issue.
98
+
99
+ ## 📅 更新记录
100
+ ### V2 版本
101
+ 1. 20250623 release V2.1.0 禁用激进的性能优化选项. 显示系统信息.
102
+ 2. 20250609 release V2.0.0 重构了代码, 使用新的界面 (不安全版本)
103
+
104
+ ### V1 版本
105
+ 1. 20220613 更新对Linux的支持, Linux下需要配置gcc&g++
106
+ 2. 20221123 可以通过文件头手动指定不编译的文件
107
+ 3. 20230306 更新可以指定命令行头如 `Python310` 以此支持非Widnows系统下编译
108
+ 4. 20230324 更新文档
109
+ 5. 20240506 修复编译失败时遗漏复原 \_\_init\_\_.py 的问题
@@ -0,0 +1,67 @@
1
+ # AutoCython V2
2
+ 中文 | [English](https://github.com/EVA-JianJun/AutoCython/blob/master/README.en.md)
3
+
4
+ **自动 Cython:一键将 Python 文件批量编译为 `PYD / SO` 文件**
5
+ ![py_pyd](https://raw.githubusercontent.com/EVA-JianJun/GitPigBed/master/blog_files/img/AutoCython_20250623.png)
6
+
7
+ ## ✨ 特性
8
+ - 单文件/多文件批量编译
9
+ - 跨平台支持 (Windows/Linux/MacOS)
10
+ - 简洁命令行界面
11
+
12
+ ## 📦 安装
13
+ ```bash
14
+ pip install -U AutoCython-jianjun
15
+ ```
16
+
17
+ ## ⚙️ 依赖环境
18
+ ### C/C++ 编译器
19
+ - **Windows**: Visual Studio
20
+ - **Linux**: gcc & g++
21
+
22
+ **重要提示**:编译器架构必须与Python解释器一致(64位Python需64位编译器)
23
+
24
+ > 其他编译器配置请参考 [Cython](https://github.com/cython/cython) 项目
25
+
26
+ ## 🚀 使用指南
27
+ ### 命令行操作
28
+ ![命令行演示](https://raw.githubusercontent.com/EVA-JianJun/GitPigBed/master/blog_files/img/AutoCython_20250609_1.png)
29
+
30
+ ```bash
31
+ # 编译单个文件
32
+ AutoCython -f test.py
33
+
34
+ # 编译整个目录
35
+ AutoCython -p D:/python_code/ProjectPath
36
+
37
+ # 编译后删除源代码 (默认不删除)
38
+ AutoCython -d True -f test.py
39
+ AutoCython -d True -p D:/python_code/ProjectPath
40
+ ```
41
+
42
+ ### 编译界面
43
+ ![AutoCython GUI](https://raw.githubusercontent.com/EVA-JianJun/GitPigBed/master/blog_files/img/AutoCython_20250609_2.png)
44
+
45
+ ### 手动排除文件不编译
46
+ 在文件头部 **前两行** 添加声明:
47
+ ```python
48
+ # AutoCython No Compile
49
+ # 此文件将跳过编译处理
50
+ ```
51
+
52
+ ## ⚠️ 常见问题解决
53
+
54
+ 一般是源代码中有 Cython 不支持的语句, 或者文件名不支持等.
55
+ 可以查阅 [Cython Wiki](https://github.com/cython/cython/wiki) 项目 官方文档, 或者提 Issue.
56
+
57
+ ## 📅 更新记录
58
+ ### V2 版本
59
+ 1. 20250623 release V2.1.0 禁用激进的性能优化选项. 显示系统信息.
60
+ 2. 20250609 release V2.0.0 重构了代码, 使用新的界面 (不安全版本)
61
+
62
+ ### V1 版本
63
+ 1. 20220613 更新对Linux的支持, Linux下需要配置gcc&g++
64
+ 2. 20221123 可以通过文件头手动指定不编译的文件
65
+ 3. 20230306 更新可以指定命令行头如 `Python310` 以此支持非Widnows系统下编译
66
+ 4. 20230324 更新文档
67
+ 5. 20240506 修复编译失败时遗漏复原 \_\_init\_\_.py 的问题
@@ -0,0 +1,31 @@
1
+ [build-system]
2
+ requires = ["setuptools", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "AutoCython-zhang"
7
+ version = "2.2.0"
8
+ authors = [{name = "zhang_gavin", email = "qq814608@163.com"}]
9
+ description = "自动Cython,使用Cython批量编译.py文件为.pyd文件!"
10
+ readme = "README.md"
11
+ license = {file = "LICENSE"}
12
+ keywords = ["cython", "compile", "pyd", "pyc", "python", "autopyd"]
13
+ classifiers = [
14
+ "Programming Language :: Python :: 3",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Operating System :: OS Independent",
17
+ ]
18
+ dependencies = [
19
+ "setuptools",
20
+ "cython",
21
+ "rich",
22
+ "tomli; python_version < '3.11'",
23
+ ]
24
+
25
+ [project.urls]
26
+ homepage = "https://github.com/zhang0281/AutoCython"
27
+ repository = "https://github.com/zhang0281/AutoCython"
28
+ documentation = "https://github.com/zhang0281/AutoCython#readme"
29
+
30
+ [project.scripts]
31
+ AutoCython = "AutoCython:main"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+