multi-lang-build 0.2.5__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.
- multi_lang_build/__init__.py +64 -0
- multi_lang_build/cli.py +320 -0
- multi_lang_build/compiler/__init__.py +22 -0
- multi_lang_build/compiler/base.py +309 -0
- multi_lang_build/compiler/go.py +468 -0
- multi_lang_build/compiler/pnpm.py +481 -0
- multi_lang_build/compiler/python.py +539 -0
- multi_lang_build/mirror/__init__.py +21 -0
- multi_lang_build/mirror/cli.py +340 -0
- multi_lang_build/mirror/config.py +251 -0
- multi_lang_build/py.typed +2 -0
- multi_lang_build/register.py +412 -0
- multi_lang_build/types.py +43 -0
- multi_lang_build-0.2.5.dist-info/METADATA +402 -0
- multi_lang_build-0.2.5.dist-info/RECORD +18 -0
- multi_lang_build-0.2.5.dist-info/WHEEL +4 -0
- multi_lang_build-0.2.5.dist-info/entry_points.txt +7 -0
- multi_lang_build-0.2.5.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
"""Python compiler with mirror acceleration support."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Final
|
|
5
|
+
import shutil
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
import venv
|
|
9
|
+
import json
|
|
10
|
+
import time
|
|
11
|
+
|
|
12
|
+
from multi_lang_build.compiler.base import CompilerBase, BuildResult, CompilerInfo
|
|
13
|
+
from multi_lang_build.mirror.config import (
|
|
14
|
+
get_mirror_config,
|
|
15
|
+
apply_mirror_environment,
|
|
16
|
+
PYPI_MIRROR_TSINGHUA,
|
|
17
|
+
PYPI_MIRROR_ALIYUN,
|
|
18
|
+
PYPI_MIRROR_DOUBAN,
|
|
19
|
+
PYPI_MIRROR_HUAWEI,
|
|
20
|
+
DEFAULT_PIP_MIRROR,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class PythonCompiler(CompilerBase):
|
|
25
|
+
"""Compiler for Python projects with pip and poetry support."""
|
|
26
|
+
|
|
27
|
+
NAME: Final[str] = "python"
|
|
28
|
+
DEFAULT_MIRROR: Final[str] = DEFAULT_PIP_MIRROR
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
python_path: str | None = None,
|
|
33
|
+
mirror: str | None = None,
|
|
34
|
+
) -> None:
|
|
35
|
+
"""Initialize the Python compiler.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
python_path: Optional path to python executable. If None, uses sys.executable.
|
|
39
|
+
mirror: Mirror configuration name (e.g., "pip", "pip_aliyun", "pip_douban", "pip_huawei").
|
|
40
|
+
Defaults to DEFAULT_PIP_MIRROR (Tsinghua).
|
|
41
|
+
"""
|
|
42
|
+
self._python_path = python_path
|
|
43
|
+
self._mirror = mirror
|
|
44
|
+
self._version_cache: str | None = None
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def name(self) -> str:
|
|
48
|
+
"""Get the compiler name."""
|
|
49
|
+
return self.NAME
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def version(self) -> str:
|
|
53
|
+
"""Get the Python version."""
|
|
54
|
+
if self._version_cache:
|
|
55
|
+
return self._version_cache
|
|
56
|
+
|
|
57
|
+
python_executable = self._get_executable_path()
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
result = subprocess.run(
|
|
61
|
+
[python_executable, "--version"],
|
|
62
|
+
capture_output=True,
|
|
63
|
+
text=True,
|
|
64
|
+
timeout=10,
|
|
65
|
+
)
|
|
66
|
+
output = result.stdout.strip() or result.stderr.strip()
|
|
67
|
+
self._version_cache = output.replace("Python ", "")
|
|
68
|
+
except Exception:
|
|
69
|
+
self._version_cache = sys.version.split()[0]
|
|
70
|
+
|
|
71
|
+
return self._version_cache
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def supported_mirrors(self) -> list[str]:
|
|
75
|
+
"""Get list of supported mirror configurations."""
|
|
76
|
+
return ["pip", "pip_aliyun", "pip_douban", "pip_huawei"]
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def current_mirror(self) -> str:
|
|
80
|
+
"""Get the current mirror configuration name."""
|
|
81
|
+
return self._mirror or "pip"
|
|
82
|
+
|
|
83
|
+
def get_info(self) -> CompilerInfo:
|
|
84
|
+
"""Get compiler information."""
|
|
85
|
+
return {
|
|
86
|
+
"name": self.name,
|
|
87
|
+
"version": self.version,
|
|
88
|
+
"supported_mirrors": self.supported_mirrors,
|
|
89
|
+
"default_mirror": self.DEFAULT_MIRROR,
|
|
90
|
+
"executable": self._get_executable_path(),
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
def set_mirror(self, mirror: str) -> None:
|
|
94
|
+
"""Set the mirror configuration.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
mirror: Mirror configuration name (e.g., "pip", "pip_aliyun", "pip_douban", "pip_huawei")
|
|
98
|
+
"""
|
|
99
|
+
self._mirror = mirror
|
|
100
|
+
|
|
101
|
+
def build(
|
|
102
|
+
self,
|
|
103
|
+
source_dir: Path,
|
|
104
|
+
output_dir: Path,
|
|
105
|
+
*,
|
|
106
|
+
environment: dict[str, str] | None = None,
|
|
107
|
+
mirror_enabled: bool = True,
|
|
108
|
+
extra_args: list[str] | None = None,
|
|
109
|
+
stream_output: bool = True,
|
|
110
|
+
) -> BuildResult:
|
|
111
|
+
"""Execute the Python build process.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
source_dir: Source code directory
|
|
115
|
+
output_dir: Build output directory
|
|
116
|
+
environment: Additional environment variables
|
|
117
|
+
mirror_enabled: Whether to use PyPI mirror
|
|
118
|
+
extra_args: Additional arguments to pass to build command
|
|
119
|
+
stream_output: Whether to stream output in real-time (default: True)
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
BuildResult containing success status and output information.
|
|
123
|
+
"""
|
|
124
|
+
python_executable = self._get_executable_path()
|
|
125
|
+
|
|
126
|
+
# Validate directories
|
|
127
|
+
source_dir = self._validate_directory(source_dir, create_if_not_exists=False)
|
|
128
|
+
output_dir = self._validate_directory(output_dir, create_if_not_exists=True)
|
|
129
|
+
|
|
130
|
+
# Prepare environment
|
|
131
|
+
env = environment.copy() if environment else {}
|
|
132
|
+
|
|
133
|
+
if mirror_enabled:
|
|
134
|
+
env = apply_mirror_environment("python", env)
|
|
135
|
+
env = apply_mirror_environment("pip", env)
|
|
136
|
+
|
|
137
|
+
# Determine build system
|
|
138
|
+
build_system = self._detect_build_system(source_dir)
|
|
139
|
+
|
|
140
|
+
if build_system == "poetry":
|
|
141
|
+
return self._build_with_poetry(
|
|
142
|
+
python_executable, source_dir, output_dir, env, extra_args, stream_output
|
|
143
|
+
)
|
|
144
|
+
elif build_system == "setuptools":
|
|
145
|
+
return self._build_with_setuptools(
|
|
146
|
+
python_executable, source_dir, output_dir, env, extra_args, stream_output
|
|
147
|
+
)
|
|
148
|
+
elif build_system == "pdm":
|
|
149
|
+
return self._build_with_pdm(
|
|
150
|
+
python_executable, source_dir, output_dir, env, extra_args, stream_output
|
|
151
|
+
)
|
|
152
|
+
else:
|
|
153
|
+
return BuildResult(
|
|
154
|
+
success=False,
|
|
155
|
+
return_code=-1,
|
|
156
|
+
stdout="",
|
|
157
|
+
stderr=f"No supported build system found in {source_dir}. "
|
|
158
|
+
"Expected pyproject.toml, setup.py, or setup.cfg",
|
|
159
|
+
output_path=None,
|
|
160
|
+
duration_seconds=0.0,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
def _detect_build_system(self, source_dir: Path) -> str:
|
|
164
|
+
"""Detect the build system used by the project.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
source_dir: Source directory to check
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
Build system name: "poetry", "setuptools", "pdm", or "none"
|
|
171
|
+
"""
|
|
172
|
+
pyproject = source_dir / "pyproject.toml"
|
|
173
|
+
setup_py = source_dir / "setup.py"
|
|
174
|
+
setup_cfg = source_dir / "setup.cfg"
|
|
175
|
+
pdm_pyproject = source_dir / "pyproject.toml"
|
|
176
|
+
|
|
177
|
+
# Check for poetry
|
|
178
|
+
if pyproject.exists():
|
|
179
|
+
try:
|
|
180
|
+
content = pyproject.read_text()
|
|
181
|
+
if "[tool.poetry]" in content:
|
|
182
|
+
return "poetry"
|
|
183
|
+
if "[tool.pdm]" in content:
|
|
184
|
+
return "pdm"
|
|
185
|
+
except Exception:
|
|
186
|
+
pass
|
|
187
|
+
|
|
188
|
+
# Check for setuptools
|
|
189
|
+
if setup_py.exists() or setup_cfg.exists():
|
|
190
|
+
return "setuptools"
|
|
191
|
+
|
|
192
|
+
# Check pdm
|
|
193
|
+
if pdm_pyproject.exists():
|
|
194
|
+
return "pdm"
|
|
195
|
+
|
|
196
|
+
return "none"
|
|
197
|
+
|
|
198
|
+
def _build_with_poetry(
|
|
199
|
+
self,
|
|
200
|
+
python_executable: str,
|
|
201
|
+
source_dir: Path,
|
|
202
|
+
output_dir: Path,
|
|
203
|
+
env: dict[str, str],
|
|
204
|
+
extra_args: list[str] | None = None,
|
|
205
|
+
stream_output: bool = True,
|
|
206
|
+
) -> BuildResult:
|
|
207
|
+
"""Build using Poetry."""
|
|
208
|
+
# Install dependencies
|
|
209
|
+
install_cmd = [python_executable, "-m", "poetry", "install"]
|
|
210
|
+
|
|
211
|
+
install_result = self._run_build(
|
|
212
|
+
install_cmd,
|
|
213
|
+
source_dir,
|
|
214
|
+
output_dir,
|
|
215
|
+
environment=env,
|
|
216
|
+
stream_output=stream_output,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
if not install_result["success"]:
|
|
220
|
+
return install_result
|
|
221
|
+
|
|
222
|
+
# Build package
|
|
223
|
+
build_cmd = [python_executable, "-m", "poetry", "build"]
|
|
224
|
+
|
|
225
|
+
if extra_args:
|
|
226
|
+
build_cmd.extend(extra_args)
|
|
227
|
+
|
|
228
|
+
return self._run_build(
|
|
229
|
+
build_cmd,
|
|
230
|
+
source_dir,
|
|
231
|
+
output_dir,
|
|
232
|
+
environment=env,
|
|
233
|
+
stream_output=stream_output,
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
def _build_with_setuptools(
|
|
237
|
+
self,
|
|
238
|
+
python_executable: str,
|
|
239
|
+
source_dir: Path,
|
|
240
|
+
output_dir: Path,
|
|
241
|
+
env: dict[str, str],
|
|
242
|
+
extra_args: list[str] | None = None,
|
|
243
|
+
stream_output: bool = True,
|
|
244
|
+
) -> BuildResult:
|
|
245
|
+
"""Build using setuptools."""
|
|
246
|
+
# Install build dependencies first
|
|
247
|
+
if (source_dir / "pyproject.toml").exists():
|
|
248
|
+
# Use build module for modern setuptools
|
|
249
|
+
build_cmd = [python_executable, "-m", "build", "--outdir", str(output_dir)]
|
|
250
|
+
else:
|
|
251
|
+
# Legacy setup.py
|
|
252
|
+
build_cmd = [python_executable, "setup.py", "bdist_wheel", "--dist-dir", str(output_dir)]
|
|
253
|
+
|
|
254
|
+
if extra_args:
|
|
255
|
+
build_cmd.extend(extra_args)
|
|
256
|
+
|
|
257
|
+
return self._run_build(
|
|
258
|
+
build_cmd,
|
|
259
|
+
source_dir,
|
|
260
|
+
output_dir,
|
|
261
|
+
environment=env,
|
|
262
|
+
stream_output=stream_output,
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
def _build_with_pdm(
|
|
266
|
+
self,
|
|
267
|
+
python_executable: str,
|
|
268
|
+
source_dir: Path,
|
|
269
|
+
output_dir: Path,
|
|
270
|
+
env: dict[str, str],
|
|
271
|
+
extra_args: list[str] | None = None,
|
|
272
|
+
stream_output: bool = True,
|
|
273
|
+
) -> BuildResult:
|
|
274
|
+
"""Build using PDM."""
|
|
275
|
+
# Build with PDM
|
|
276
|
+
build_cmd = [python_executable, "-m", "pdm", "build"]
|
|
277
|
+
|
|
278
|
+
if extra_args:
|
|
279
|
+
build_cmd.extend(extra_args)
|
|
280
|
+
|
|
281
|
+
return self._run_build(
|
|
282
|
+
build_cmd,
|
|
283
|
+
source_dir,
|
|
284
|
+
output_dir,
|
|
285
|
+
environment=env,
|
|
286
|
+
stream_output=stream_output,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
def install_dependencies(
|
|
290
|
+
self,
|
|
291
|
+
source_dir: Path,
|
|
292
|
+
*,
|
|
293
|
+
environment: dict[str, str] | None = None,
|
|
294
|
+
mirror_enabled: bool = True,
|
|
295
|
+
dev: bool = False,
|
|
296
|
+
poetry: bool = False,
|
|
297
|
+
) -> BuildResult:
|
|
298
|
+
"""Install Python dependencies.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
source_dir: Source code directory
|
|
302
|
+
environment: Additional environment variables
|
|
303
|
+
mirror_enabled: Whether to use PyPI mirror
|
|
304
|
+
dev: Include development dependencies
|
|
305
|
+
poetry: Force using poetry
|
|
306
|
+
|
|
307
|
+
Returns:
|
|
308
|
+
BuildResult containing success status and output information.
|
|
309
|
+
"""
|
|
310
|
+
python_executable = self._get_executable_path()
|
|
311
|
+
|
|
312
|
+
source_dir = self._validate_directory(source_dir, create_if_not_exists=False)
|
|
313
|
+
|
|
314
|
+
env = environment.copy() if environment else {}
|
|
315
|
+
|
|
316
|
+
if mirror_enabled:
|
|
317
|
+
env = apply_mirror_environment("pip", env)
|
|
318
|
+
|
|
319
|
+
# Check for poetry first
|
|
320
|
+
if poetry or (source_dir / "pyproject.toml").exists() and "poetry" in (source_dir / "pyproject.toml").read_text():
|
|
321
|
+
cmd = [python_executable, "-m", "poetry", "install"]
|
|
322
|
+
if dev:
|
|
323
|
+
cmd.append("--with=dev")
|
|
324
|
+
return self._run_build(cmd, source_dir, source_dir, environment=env)
|
|
325
|
+
|
|
326
|
+
# Use pip
|
|
327
|
+
cmd = [python_executable, "-m", "pip", "install", "-r", str(source_dir / "requirements.txt")]
|
|
328
|
+
|
|
329
|
+
if dev:
|
|
330
|
+
cmd.append("-r")
|
|
331
|
+
cmd.append(str(source_dir / "requirements-dev.txt"))
|
|
332
|
+
|
|
333
|
+
return self._run_build(cmd, source_dir, source_dir, environment=env)
|
|
334
|
+
|
|
335
|
+
def create_venv(
|
|
336
|
+
self,
|
|
337
|
+
directory: Path,
|
|
338
|
+
*,
|
|
339
|
+
python_path: str | None = None,
|
|
340
|
+
mirror_enabled: bool = True,
|
|
341
|
+
) -> BuildResult:
|
|
342
|
+
"""Create a virtual environment.
|
|
343
|
+
|
|
344
|
+
Args:
|
|
345
|
+
directory: Directory to create the venv in
|
|
346
|
+
python_path: Python interpreter to use
|
|
347
|
+
mirror_enabled: Whether to configure pip mirror
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
BuildResult containing success status and output information.
|
|
351
|
+
"""
|
|
352
|
+
env_builder = venv.EnvBuilder(with_pip=True, clear=True)
|
|
353
|
+
|
|
354
|
+
start_time = time.perf_counter() # noqa: F821
|
|
355
|
+
|
|
356
|
+
try:
|
|
357
|
+
env_builder.create(directory)
|
|
358
|
+
|
|
359
|
+
# Configure pip mirror if enabled
|
|
360
|
+
if mirror_enabled:
|
|
361
|
+
pip_config_dir = directory / "pip.conf"
|
|
362
|
+
pip_config_dir.write_text(
|
|
363
|
+
"[global]\n"
|
|
364
|
+
"index-url = https://pypi.tuna.tsinghua.edu.cn/simple\n"
|
|
365
|
+
"trusted-host = pypi.tuna.tsinghua.edu.cn\n"
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
duration = time.perf_counter() - start_time # noqa: F821
|
|
369
|
+
|
|
370
|
+
return BuildResult(
|
|
371
|
+
success=True,
|
|
372
|
+
return_code=0,
|
|
373
|
+
stdout=f"Virtual environment created at {directory}",
|
|
374
|
+
stderr="",
|
|
375
|
+
output_path=directory,
|
|
376
|
+
duration_seconds=duration,
|
|
377
|
+
)
|
|
378
|
+
except Exception as e:
|
|
379
|
+
duration = time.perf_counter() - start_time # noqa: F821
|
|
380
|
+
return BuildResult(
|
|
381
|
+
success=False,
|
|
382
|
+
return_code=-1,
|
|
383
|
+
stdout="",
|
|
384
|
+
stderr=f"Failed to create virtual environment: {str(e)}",
|
|
385
|
+
output_path=None,
|
|
386
|
+
duration_seconds=duration,
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
def run_script(
|
|
390
|
+
self,
|
|
391
|
+
source_dir: Path,
|
|
392
|
+
script_name: str,
|
|
393
|
+
*,
|
|
394
|
+
environment: dict[str, str] | None = None,
|
|
395
|
+
mirror_enabled: bool = True,
|
|
396
|
+
) -> BuildResult:
|
|
397
|
+
"""Run a Python script or module.
|
|
398
|
+
|
|
399
|
+
Args:
|
|
400
|
+
source_dir: Source code directory
|
|
401
|
+
script_name: Script or module name to run
|
|
402
|
+
environment: Additional environment variables
|
|
403
|
+
mirror_enabled: Whether to use PyPI mirror
|
|
404
|
+
|
|
405
|
+
Returns:
|
|
406
|
+
BuildResult containing success status and output information.
|
|
407
|
+
"""
|
|
408
|
+
python_executable = self._get_executable_path()
|
|
409
|
+
|
|
410
|
+
source_dir = self._validate_directory(source_dir, create_if_not_exists=False)
|
|
411
|
+
|
|
412
|
+
env = environment.copy() if environment else {}
|
|
413
|
+
|
|
414
|
+
if mirror_enabled:
|
|
415
|
+
env = apply_mirror_environment("pip", env)
|
|
416
|
+
|
|
417
|
+
return self._run_build(
|
|
418
|
+
[python_executable, "-m", script_name],
|
|
419
|
+
source_dir,
|
|
420
|
+
source_dir,
|
|
421
|
+
environment=env,
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
def clean(self, directory: Path) -> bool:
|
|
425
|
+
"""Clean Python build artifacts in the specified directory.
|
|
426
|
+
|
|
427
|
+
Args:
|
|
428
|
+
directory: Directory to clean
|
|
429
|
+
|
|
430
|
+
Returns:
|
|
431
|
+
True if successful, False otherwise.
|
|
432
|
+
"""
|
|
433
|
+
import shutil
|
|
434
|
+
|
|
435
|
+
try:
|
|
436
|
+
directory = self._validate_directory(directory, create_if_not_exists=False)
|
|
437
|
+
|
|
438
|
+
# Remove __pycache__ directories
|
|
439
|
+
for pycache in directory.rglob("__pycache__"):
|
|
440
|
+
shutil.rmtree(pycache)
|
|
441
|
+
|
|
442
|
+
# Remove .pyc files
|
|
443
|
+
for pyc in directory.rglob("*.pyc"):
|
|
444
|
+
pyc.unlink()
|
|
445
|
+
|
|
446
|
+
# Remove .pytest_cache
|
|
447
|
+
pytest_cache = directory / ".pytest_cache"
|
|
448
|
+
if pytest_cache.exists():
|
|
449
|
+
shutil.rmtree(pytest_cache)
|
|
450
|
+
|
|
451
|
+
# Remove .tox
|
|
452
|
+
tox_dir = directory / ".tox"
|
|
453
|
+
if tox_dir.exists():
|
|
454
|
+
shutil.rmtree(tox_dir)
|
|
455
|
+
|
|
456
|
+
# Remove dist directory
|
|
457
|
+
dist_dir = directory / "dist"
|
|
458
|
+
if dist_dir.exists():
|
|
459
|
+
shutil.rmtree(dist_dir)
|
|
460
|
+
|
|
461
|
+
# Remove build directory
|
|
462
|
+
build_dir = directory / "build"
|
|
463
|
+
if build_dir.exists():
|
|
464
|
+
shutil.rmtree(build_dir)
|
|
465
|
+
|
|
466
|
+
# Remove *.egg-info directories
|
|
467
|
+
for egg_info in directory.rglob("*.egg-info"):
|
|
468
|
+
shutil.rmtree(egg_info)
|
|
469
|
+
|
|
470
|
+
return True
|
|
471
|
+
|
|
472
|
+
except Exception:
|
|
473
|
+
return False
|
|
474
|
+
|
|
475
|
+
def _get_executable_path(self) -> str:
|
|
476
|
+
"""Get the python executable path."""
|
|
477
|
+
if self._python_path:
|
|
478
|
+
return self._python_path
|
|
479
|
+
|
|
480
|
+
python_path = shutil.which("python3") or shutil.which("python")
|
|
481
|
+
if python_path is None:
|
|
482
|
+
return sys.executable
|
|
483
|
+
|
|
484
|
+
return python_path
|
|
485
|
+
|
|
486
|
+
@staticmethod
|
|
487
|
+
def create(source_dir: Path, *, mirror_enabled: bool = True) -> "PythonCompiler":
|
|
488
|
+
"""Factory method to create a PythonCompiler instance.
|
|
489
|
+
|
|
490
|
+
Args:
|
|
491
|
+
source_dir: Source directory for the project
|
|
492
|
+
mirror_enabled: Whether to enable mirror acceleration by default
|
|
493
|
+
|
|
494
|
+
Returns:
|
|
495
|
+
Configured PythonCompiler instance
|
|
496
|
+
"""
|
|
497
|
+
compiler = PythonCompiler()
|
|
498
|
+
return compiler
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def main() -> None:
|
|
502
|
+
"""Python compiler CLI entry point."""
|
|
503
|
+
import argparse
|
|
504
|
+
import sys
|
|
505
|
+
|
|
506
|
+
parser = argparse.ArgumentParser(description="Python Build Compiler")
|
|
507
|
+
parser.add_argument("source_dir", type=Path, help="Source directory")
|
|
508
|
+
parser.add_argument("-o", "--output", type=Path, required=True, help="Output directory")
|
|
509
|
+
parser.add_argument("--mirror", action="store_true", default=True, help="Enable PyPI mirror")
|
|
510
|
+
parser.add_argument("--no-mirror", dest="mirror", action="store_false", help="Disable PyPI mirror")
|
|
511
|
+
parser.add_argument("--install", action="store_true", help="Install dependencies only")
|
|
512
|
+
parser.add_argument("--dev", action="store_true", help="Include dev dependencies")
|
|
513
|
+
parser.add_argument("--poetry", action="store_true", help="Force using poetry")
|
|
514
|
+
parser.add_argument("--create-venv", type=Path, help="Create virtual environment at path")
|
|
515
|
+
|
|
516
|
+
args = parser.parse_args()
|
|
517
|
+
|
|
518
|
+
compiler = PythonCompiler()
|
|
519
|
+
|
|
520
|
+
if args.create_venv:
|
|
521
|
+
result = compiler.create_venv(
|
|
522
|
+
args.create_venv,
|
|
523
|
+
mirror_enabled=args.mirror,
|
|
524
|
+
)
|
|
525
|
+
elif args.install:
|
|
526
|
+
result = compiler.install_dependencies(
|
|
527
|
+
args.source_dir,
|
|
528
|
+
mirror_enabled=args.mirror,
|
|
529
|
+
dev=args.dev,
|
|
530
|
+
poetry=args.poetry,
|
|
531
|
+
)
|
|
532
|
+
else:
|
|
533
|
+
result = compiler.build(
|
|
534
|
+
args.source_dir,
|
|
535
|
+
args.output,
|
|
536
|
+
mirror_enabled=args.mirror,
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
sys.exit(0 if result["success"] else 1)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Mirror configuration module for domestic acceleration."""
|
|
2
|
+
|
|
3
|
+
from multi_lang_build.mirror.config import (
|
|
4
|
+
MirrorConfig,
|
|
5
|
+
MIRROR_CONFIGS,
|
|
6
|
+
get_mirror_config,
|
|
7
|
+
apply_mirror_environment,
|
|
8
|
+
reset_mirror_environment,
|
|
9
|
+
get_all_mirror_names,
|
|
10
|
+
validate_mirror_config,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"MirrorConfig",
|
|
15
|
+
"MIRROR_CONFIGS",
|
|
16
|
+
"get_mirror_config",
|
|
17
|
+
"apply_mirror_environment",
|
|
18
|
+
"reset_mirror_environment",
|
|
19
|
+
"get_all_mirror_names",
|
|
20
|
+
"validate_mirror_config",
|
|
21
|
+
]
|