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.
@@ -0,0 +1,340 @@
1
+ """Mirror configuration CLI for domestic acceleration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ import subprocess
8
+ import sys
9
+ from pathlib import Path
10
+ from typing import Literal
11
+
12
+
13
+ def get_all_mirrors() -> dict:
14
+ """Get all available mirrors with their configurations."""
15
+ from multi_lang_build.mirror.config import MIRROR_CONFIGS
16
+
17
+ mirrors = {}
18
+ for key, config in MIRROR_CONFIGS.items():
19
+ mirrors[key] = {
20
+ "name": config["name"],
21
+ "url": config["url"],
22
+ }
23
+ return mirrors
24
+
25
+
26
+ def print_mirrors() -> None:
27
+ """Print all available mirrors."""
28
+ mirrors = get_all_mirrors()
29
+
30
+ print("\nšŸ“¦ Available Mirrors:")
31
+ print("-" * 60)
32
+
33
+ # Group by category
34
+ categories = {
35
+ "js": ["npm", "pnpm", "yarn"],
36
+ "go": ["go", "go_qiniu", "go_vip"],
37
+ "python": ["pip", "pip_aliyun", "pip_douban", "pip_huawei", "python", "poetry"],
38
+ }
39
+
40
+ category_names = {
41
+ "js": "🌐 JavaScript (npm/pnpm/yarn)",
42
+ "go": "šŸ”· Go",
43
+ "python": "šŸ Python (pip/PyPI)",
44
+ }
45
+
46
+ for cat_key, cat_mirrors in categories.items():
47
+ print(f"\n{category_names.get(cat_key, cat_key)}")
48
+ for mirror_key in cat_mirrors:
49
+ if mirror_key in mirrors:
50
+ config = mirrors[mirror_key]
51
+ print(f" • {mirror_key:12} - {config['name']}")
52
+ print(f" {config['url']}")
53
+
54
+ print()
55
+
56
+
57
+ def configure_pip(mirror_key: str) -> bool:
58
+ """Configure pip mirror using pip config command."""
59
+ from multi_lang_build.mirror.config import get_mirror_config
60
+
61
+ config = get_mirror_config(mirror_key)
62
+ if config is None:
63
+ print(f"āŒ Unknown pip mirror: {mirror_key}")
64
+ return False
65
+
66
+ url = config["url"]
67
+ if not url.endswith("/simple") and not url.endswith("/simple/"):
68
+ url = f"{url}/simple"
69
+
70
+ # Try pip3 first, fallback to pip
71
+ pip_cmd = "pip3" if sys.platform != "win32" else "pip"
72
+
73
+ try:
74
+ subprocess.run(
75
+ [pip_cmd, "config", "set", "global.index-url", url],
76
+ check=True,
77
+ )
78
+ print(f"āœ… pip mirror set to: {url}")
79
+ return True
80
+ except subprocess.CalledProcessError as e:
81
+ print(f"āŒ Failed to set pip mirror: {e}")
82
+ return False
83
+ except FileNotFoundError:
84
+ # Try alternative
85
+ try:
86
+ alternative = "pip" if pip_cmd == "pip3" else "pip3"
87
+ subprocess.run(
88
+ [alternative, "config", "set", "global.index-url", url],
89
+ check=True,
90
+ )
91
+ print(f"āœ… pip mirror set to: {url}")
92
+ return True
93
+ except Exception:
94
+ print("āŒ pip/pip3 not found")
95
+ return False
96
+
97
+
98
+ def configure_go(mirror_key: str) -> bool:
99
+ """Configure Go proxy using go env -w."""
100
+ from multi_lang_build.mirror.config import get_mirror_config
101
+
102
+ config = get_mirror_config(mirror_key)
103
+ if config is None:
104
+ print(f"āŒ Unknown Go mirror: {mirror_key}")
105
+ return False
106
+
107
+ # Get the GOPROXY value from environment variables
108
+ proxy_value = config["environment_variables"].get("GOPROXY", f"{config['url']},direct")
109
+
110
+ try:
111
+ subprocess.run(
112
+ ["go", "env", "-w", f"GOPROXY={proxy_value}"],
113
+ check=True,
114
+ )
115
+ print(f"āœ… Go GOPROXY set to: {proxy_value}")
116
+
117
+ # Also set GOSUMDB if present
118
+ gosumdb = config["environment_variables"].get("GOSUMDB")
119
+ if gosumdb:
120
+ subprocess.run(
121
+ ["go", "env", "-w", f"GOSUMDB={gosumdb}"],
122
+ check=True,
123
+ )
124
+ print(f"āœ… Go GOSUMDB set to: {gosumdb}")
125
+
126
+ return True
127
+ except subprocess.CalledProcessError as e:
128
+ print(f"āŒ Failed to set Go mirror: {e}")
129
+ return False
130
+ except FileNotFoundError:
131
+ print("āŒ go not found")
132
+ return False
133
+
134
+
135
+ def configure_npm(mirror_key: str) -> bool:
136
+ """Configure npm/pnpm registry."""
137
+ from multi_lang_build.mirror.config import get_mirror_config
138
+
139
+ config = get_mirror_config(mirror_key)
140
+ if config is None:
141
+ print(f"āŒ Unknown npm mirror: {mirror_key}")
142
+ return False
143
+
144
+ url = config["url"]
145
+
146
+ try:
147
+ subprocess.run(
148
+ ["npm", "config", "set", "registry", url],
149
+ check=True,
150
+ )
151
+ print(f"āœ… npm registry set to: {url}")
152
+
153
+ # Also set for pnpm if available
154
+ try:
155
+ subprocess.run(
156
+ ["pnpm", "config", "set", "registry", url],
157
+ check=True,
158
+ )
159
+ print(f"āœ… pnpm registry set to: {url}")
160
+ except (subprocess.CalledProcessError, FileNotFoundError):
161
+ pass
162
+
163
+ return True
164
+ except subprocess.CalledProcessError as e:
165
+ print(f"āŒ Failed to set npm registry: {e}")
166
+ return False
167
+ except FileNotFoundError:
168
+ print("āŒ npm not found")
169
+ return False
170
+
171
+
172
+ def get_current_config() -> dict:
173
+ """Get current mirror configuration."""
174
+ config = {}
175
+
176
+ # Try pip3 first, fallback to pip
177
+ pip_cmd = "pip3" if sys.platform != "win32" else "pip"
178
+
179
+ try:
180
+ result = subprocess.run(
181
+ [pip_cmd, "config", "get", "global.index-url"],
182
+ capture_output=True,
183
+ text=True,
184
+ )
185
+ if result.returncode == 0 and result.stdout.strip():
186
+ config["pip"] = result.stdout.strip()
187
+ except Exception:
188
+ pass
189
+
190
+ # Check Go
191
+ try:
192
+ result = subprocess.run(
193
+ ["go", "env", "GOPROXY"],
194
+ capture_output=True,
195
+ text=True,
196
+ )
197
+ if result.returncode == 0:
198
+ config["go"] = result.stdout.strip()
199
+ except Exception:
200
+ pass
201
+
202
+ # Check npm
203
+ try:
204
+ result = subprocess.run(
205
+ ["npm", "config", "get", "registry"],
206
+ capture_output=True,
207
+ text=True,
208
+ )
209
+ if result.returncode == 0:
210
+ config["npm"] = result.stdout.strip()
211
+ except Exception:
212
+ pass
213
+
214
+ return config
215
+
216
+
217
+ def configure_mirror(mirror_type: str, mirror_key: str) -> bool:
218
+ """Configure mirror for a specific package manager.
219
+
220
+ Args:
221
+ mirror_type: Package manager type (pip, go, npm)
222
+ mirror_key: Mirror key to use
223
+
224
+ Returns:
225
+ True if successful, False otherwise
226
+ """
227
+ if mirror_type == "pip":
228
+ return configure_pip(mirror_key)
229
+ elif mirror_type == "go":
230
+ return configure_go(mirror_key)
231
+ elif mirror_type in ["npm", "pnpm"]:
232
+ return configure_npm(mirror_key)
233
+ else:
234
+ print(f"āŒ Unknown package manager: {mirror_type}")
235
+ return False
236
+
237
+
238
+ def mirror_main():
239
+ """Main entry point for mirror command."""
240
+ import argparse
241
+
242
+ parser = argparse.ArgumentParser(
243
+ description="Configure domestic mirror acceleration",
244
+ epilog="""
245
+ Examples:
246
+ %(prog)s list List all available mirrors
247
+ %(prog)s set pip Configure pip mirror (default)
248
+ %(prog)s set go Configure Go proxy
249
+ %(prog)s set npm Configure npm registry
250
+ %(prog)s show Show current configuration
251
+ """,
252
+ )
253
+ parser.add_argument(
254
+ "--version",
255
+ action="version",
256
+ version="%(prog)s 0.2.2",
257
+ )
258
+
259
+ subparsers = parser.add_subparsers(dest="command", help="Commands")
260
+
261
+ # list command
262
+ list_parser = subparsers.add_parser("list", help="List available mirrors")
263
+ list_parser.add_argument(
264
+ "--json",
265
+ action="store_true",
266
+ help="Output as JSON",
267
+ )
268
+ list_parser.add_argument(
269
+ "--type",
270
+ type=str,
271
+ choices=["pip", "go", "npm"],
272
+ help="Filter by type",
273
+ )
274
+
275
+ # set command
276
+ set_parser = subparsers.add_parser("set", help="Configure mirror")
277
+ set_parser.add_argument(
278
+ "type",
279
+ type=str,
280
+ default="pip",
281
+ nargs="?",
282
+ choices=["pip", "go", "npm", "pnpm"],
283
+ help="Package manager type (default: pip)",
284
+ )
285
+ set_parser.add_argument(
286
+ "mirror",
287
+ type=str,
288
+ nargs="?",
289
+ default="pip",
290
+ help="Mirror to use",
291
+ )
292
+
293
+ # show command
294
+ show_parser = subparsers.add_parser("show", help="Show current mirror configuration")
295
+
296
+ args = parser.parse_args()
297
+
298
+ if args.command == "list":
299
+ mirrors = get_all_mirrors()
300
+ if getattr(args, "json", False):
301
+ print(json.dumps(mirrors, indent=2, ensure_ascii=False))
302
+ else:
303
+ print_mirrors()
304
+
305
+ elif args.command == "set":
306
+ mirror_type = args.type
307
+ mirror_key = args.mirror
308
+ success = configure_mirror(mirror_type, mirror_key)
309
+ sys.exit(0 if success else 1)
310
+
311
+ elif args.command == "show":
312
+ config = get_current_config()
313
+ if config:
314
+ print("\nšŸ“¦ Current Mirror Configuration:")
315
+ print("-" * 40)
316
+ for key, value in config.items():
317
+ print(f" • {key}: {value}")
318
+ print()
319
+ else:
320
+ print("\nšŸ“¦ No mirror configured")
321
+ print(" Run 'multi-lang-build mirror set <type> <mirror>' to configure")
322
+ print()
323
+ print_mirrors()
324
+
325
+ else:
326
+ # No subcommand, show help
327
+ parser.print_help()
328
+ print("\nšŸ“‹ Commands:")
329
+ print(" list List all available mirrors")
330
+ print(" set <type> <name> Configure mirror (type: pip/go/npm)")
331
+ print(" show Show current configuration")
332
+ print("\nšŸ“‹ Examples:")
333
+ print(" multi-lang-build mirror list")
334
+ print(" multi-lang-build mirror set pip")
335
+ print(" multi-lang-build mirror set go")
336
+ print(" multi-lang-build mirror set npm")
337
+
338
+
339
+ if __name__ == "__main__":
340
+ mirror_main()
@@ -0,0 +1,251 @@
1
+ """Mirror configuration for domestic acceleration."""
2
+
3
+ from typing import TypedDict, Literal
4
+ from pathlib import Path
5
+
6
+
7
+ # ============================================================================
8
+ # Constants for mainstream domestic mirrors
9
+ # ============================================================================
10
+
11
+ # NPM/PNPM mirrors
12
+ NPM_REGISTRY_NPMMIRROR: Literal["https://registry.npmmirror.com"] = "https://registry.npmmirror.com"
13
+ NPM_REGISTRY_TAOBAO: Literal["https://registry.npmmirror.com"] = "https://registry.npmmirror.com" # Taobao mirrors npmmirror
14
+
15
+ # Go mirrors (including Qiniu cloud)
16
+ GO_PROXY_GOPROXY_CN: Literal["https://goproxy.cn"] = "https://goproxy.cn"
17
+ GO_PROXY_GOPROXY_IO: Literal["https://goproxy.io"] = "https://goproxy.io"
18
+ GO_PROXY_GOVIP_CN: Literal["https://goproxy.vip.cn"] = "https://goproxy.vip.cn"
19
+ GO_PROXY_FASTGOPROXY: Literal["https://goproxy.cn,direct"] = "https://goproxy.cn,direct"
20
+
21
+ # Go sumdb mirrors
22
+ GO_SUMDB_GOLANG: Literal["sum.golang.org"] = "sum.golang.org"
23
+ GO_SUMDB_GOLANG_GOOGLE_CN: Literal["sum.golang.google.cn"] = "sum.golang.google.cn"
24
+
25
+ # PyPI/Pip mirrors
26
+ PYPI_MIRROR_TSINGHUA: Literal["https://pypi.tuna.tsinghua.edu.cn"] = "https://pypi.tuna.tsinghua.edu.cn"
27
+ PYPI_MIRROR_ALIYUN: Literal["https://mirrors.aliyun.com/pypi/simple"] = "https://mirrors.aliyun.com/pypi/simple"
28
+ PYPI_MIRROR_DOUBAN: Literal["https://pypi.doubanio.com/simple"] = "https://pypi.doubanio.com/simple"
29
+ PYPI_MIRROR_HUAWEI: Literal["https://repo.huaweicloud.com/repository/pypi/simple"] = "https://repo.huaweicloud.com/repository/pypi/simple"
30
+ PYPI_MIRROR_NETEASE: Literal["https://mirrors.163.com/pypi/simple"] = "https://mirrors.163.com/pypi/simple"
31
+ PYPI_MIRROR_SAU: Literal["https://pypi.sau.edu.cn/simple"] = "https://pypi.sau.edu.cn/simple"
32
+
33
+ # Poetry mirrors (uses same PyPI mirrors)
34
+ POETRY_REPO_TSINGHUA: Literal["https://pypi.tuna.tsinghua.edu.cn/simple"] = "https://pypi.tuna.tsinghua.edu.cn/simple"
35
+ POETRY_REPO_ALIYUN: Literal["https://mirrors.aliyun.com/pypi/simple"] = "https://mirrors.aliyun.com/pypi/simple"
36
+
37
+ # Default mirror selection
38
+ DEFAULT_GO_MIRROR: str = GO_PROXY_GOPROXY_CN
39
+ DEFAULT_PIP_MIRROR: str = PYPI_MIRROR_TSINGHUA
40
+
41
+
42
+ class MirrorConfig(TypedDict):
43
+ """Mirror configuration for package managers."""
44
+ name: str
45
+ url: str
46
+ environment_prefix: str
47
+ environment_variables: dict[str, str]
48
+
49
+
50
+ # Predefined mirror configurations for different package managers
51
+ MIRROR_CONFIGS: dict[str, MirrorConfig] = {
52
+ "npm": {
53
+ "name": "NPM China Mirror (npmmirror)",
54
+ "url": NPM_REGISTRY_NPMMIRROR,
55
+ "environment_prefix": "NPM",
56
+ "environment_variables": {
57
+ "NPM_CONFIG_REGISTRY": NPM_REGISTRY_NPMMIRROR,
58
+ },
59
+ },
60
+ "pnpm": {
61
+ "name": "PNPM China Mirror (npmmirror)",
62
+ "url": NPM_REGISTRY_NPMMIRROR,
63
+ "environment_prefix": "PNPM",
64
+ "environment_variables": {
65
+ "PNPM_CONFIG_REGISTRY": NPM_REGISTRY_NPMMIRROR,
66
+ },
67
+ },
68
+ "yarn": {
69
+ "name": "Yarn China Mirror (npmmirror)",
70
+ "url": NPM_REGISTRY_NPMMIRROR,
71
+ "environment_prefix": "YARN",
72
+ "environment_variables": {
73
+ "YARN_NPM_MIRROR": NPM_REGISTRY_NPMMIRROR,
74
+ },
75
+ },
76
+ "go": {
77
+ "name": "Go China Mirror (goproxy.cn)",
78
+ "url": GO_PROXY_GOPROXY_CN,
79
+ "environment_prefix": "GOPROXY",
80
+ "environment_variables": {
81
+ "GOPROXY": f"{GO_PROXY_GOPROXY_CN},direct",
82
+ "GOSUMDB": GO_SUMDB_GOLANG_GOOGLE_CN,
83
+ },
84
+ },
85
+ "go_qiniu": {
86
+ "name": "Go China Mirror (goproxy.io)",
87
+ "url": GO_PROXY_GOPROXY_IO,
88
+ "environment_prefix": "GOPROXY",
89
+ "environment_variables": {
90
+ "GOPROXY": f"{GO_PROXY_GOPROXY_IO},direct",
91
+ "GOSUMDB": GO_SUMDB_GOLANG_GOOGLE_CN,
92
+ },
93
+ },
94
+ "go_vip": {
95
+ "name": "Go China Mirror (goproxy.vip.cn)",
96
+ "url": GO_PROXY_GOVIP_CN,
97
+ "environment_prefix": "GOPROXY",
98
+ "environment_variables": {
99
+ "GOPROXY": f"{GO_PROXY_GOVIP_CN},direct",
100
+ "GOSUMDB": GO_SUMDB_GOLANG_GOOGLE_CN,
101
+ },
102
+ },
103
+ "pip": {
104
+ "name": "Pip China Mirror (Tsinghua)",
105
+ "url": PYPI_MIRROR_TSINGHUA,
106
+ "environment_prefix": "PIP",
107
+ "environment_variables": {
108
+ "PIP_INDEX_URL": f"{PYPI_MIRROR_TSINGHUA}/simple",
109
+ "PIP_TRUSTED_HOST": "pypi.tuna.tsinghua.edu.cn",
110
+ },
111
+ },
112
+ "pip_aliyun": {
113
+ "name": "Pip China Mirror (Aliyun)",
114
+ "url": PYPI_MIRROR_ALIYUN,
115
+ "environment_prefix": "PIP",
116
+ "environment_variables": {
117
+ "PIP_INDEX_URL": f"{PYPI_MIRROR_ALIYUN}/simple",
118
+ "PIP_TRUSTED_HOST": "mirrors.aliyun.com",
119
+ },
120
+ },
121
+ "pip_douban": {
122
+ "name": "Pip China Mirror (Douban)",
123
+ "url": PYPI_MIRROR_DOUBAN,
124
+ "environment_prefix": "PIP",
125
+ "environment_variables": {
126
+ "PIP_INDEX_URL": f"{PYPI_MIRROR_DOUBAN}/simple",
127
+ "PIP_TRUSTED_HOST": "pypi.doubanio.com",
128
+ },
129
+ },
130
+ "pip_huawei": {
131
+ "name": "Pip China Mirror (Huawei)",
132
+ "url": PYPI_MIRROR_HUAWEI,
133
+ "environment_prefix": "PIP",
134
+ "environment_variables": {
135
+ "PIP_INDEX_URL": f"{PYPI_MIRROR_HUAWEI}/simple",
136
+ "PIP_TRUSTED_HOST": "repo.huaweicloud.com",
137
+ },
138
+ },
139
+ "python": {
140
+ "name": "PyPI China Mirror (Tsinghua)",
141
+ "url": PYPI_MIRROR_TSINGHUA,
142
+ "environment_prefix": "PIP",
143
+ "environment_variables": {
144
+ "PIP_INDEX_URL": f"{PYPI_MIRROR_TSINGHUA}/simple",
145
+ "PIP_TRUSTED_HOST": "pypi.tuna.tsinghua.edu.cn",
146
+ },
147
+ },
148
+ "poetry": {
149
+ "name": "Poetry China Mirror (Tsinghua)",
150
+ "url": PYPI_MIRROR_TSINGHUA,
151
+ "environment_prefix": "POETRY",
152
+ "environment_variables": {
153
+ "POETRY_REPOSITORIES_PYPI_URL": f"{POETRY_REPO_TSINGHUA}/simple",
154
+ },
155
+ },
156
+ }
157
+
158
+
159
+ def get_mirror_config(package_manager: str) -> MirrorConfig | None:
160
+ """Get mirror configuration for a specific package manager.
161
+
162
+ Args:
163
+ package_manager: Name of the package manager (e.g., "npm", "go", "pip")
164
+
165
+ Returns:
166
+ MirrorConfig if found, None otherwise.
167
+ """
168
+ normalized_name = package_manager.lower().strip()
169
+ return MIRROR_CONFIGS.get(normalized_name)
170
+
171
+
172
+ def apply_mirror_environment(
173
+ package_manager: str,
174
+ environment: dict[str, str]
175
+ ) -> dict[str, str]:
176
+ """Apply mirror environment variables to the environment dict.
177
+
178
+ Args:
179
+ package_manager: Name of the package manager
180
+ environment: Existing environment variables
181
+
182
+ Returns:
183
+ Updated environment with mirror variables added.
184
+ """
185
+ mirror_config = get_mirror_config(package_manager)
186
+ if mirror_config is None:
187
+ return environment
188
+
189
+ mirror_vars = mirror_config.get("environment_variables", {})
190
+ updated_env = environment.copy()
191
+ updated_env.update(mirror_vars)
192
+
193
+ return updated_env
194
+
195
+
196
+ def reset_mirror_environment(
197
+ package_manager: str,
198
+ environment: dict[str, str]
199
+ ) -> dict[str, str]:
200
+ """Remove mirror environment variables from the environment dict.
201
+
202
+ Args:
203
+ package_manager: Name of the package manager
204
+ environment: Existing environment variables
205
+
206
+ Returns:
207
+ Environment with mirror variables removed.
208
+ """
209
+ mirror_config = get_mirror_config(package_manager)
210
+ if mirror_config is None:
211
+ return environment
212
+
213
+ mirror_vars = mirror_config.get("environment_variables", {})
214
+ updated_env = environment.copy()
215
+
216
+ for key in mirror_vars:
217
+ updated_env.pop(key, None)
218
+
219
+ return updated_env
220
+
221
+
222
+ def get_all_mirror_names() -> list[str]:
223
+ """Get list of all available mirror names.
224
+
225
+ Returns:
226
+ List of package manager names with mirror support.
227
+ """
228
+ return list(MIRROR_CONFIGS.keys())
229
+
230
+
231
+ def validate_mirror_config(mirror_config: MirrorConfig) -> bool:
232
+ """Validate a mirror configuration.
233
+
234
+ Args:
235
+ mirror_config: Mirror configuration to validate
236
+
237
+ Returns:
238
+ True if valid, False otherwise.
239
+ """
240
+ required_fields = ["name", "url", "environment_prefix", "environment_variables"]
241
+
242
+ for field in required_fields:
243
+ if field not in mirror_config or not mirror_config[field]:
244
+ return False
245
+
246
+ # Validate URL format
247
+ url = mirror_config["url"]
248
+ if not (url.startswith("http://") or url.startswith("https://")):
249
+ return False
250
+
251
+ return True
@@ -0,0 +1,2 @@
1
+ # Marker file for PEP 561 type information
2
+ # This package uses static type checking