ruyi 0.44.0a20251118__py3-none-any.whl → 0.45.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.
- ruyi/__main__.py +16 -4
- ruyi/cli/cmd.py +6 -5
- ruyi/cli/config_cli.py +14 -11
- ruyi/cli/main.py +34 -17
- ruyi/cli/oobe.py +10 -10
- ruyi/cli/self_cli.py +49 -36
- ruyi/cli/user_input.py +42 -12
- ruyi/cli/version_cli.py +11 -5
- ruyi/config/__init__.py +30 -10
- ruyi/config/errors.py +19 -7
- ruyi/device/provision.py +116 -55
- ruyi/device/provision_cli.py +6 -3
- ruyi/i18n/__init__.py +129 -0
- ruyi/log/__init__.py +6 -5
- ruyi/mux/runtime.py +19 -6
- ruyi/mux/venv/maker.py +93 -35
- ruyi/mux/venv/venv_cli.py +13 -10
- ruyi/pluginhost/plugin_cli.py +4 -3
- ruyi/resource_bundle/__init__.py +22 -8
- ruyi/resource_bundle/__main__.py +6 -5
- ruyi/resource_bundle/data.py +13 -9
- ruyi/ruyipkg/admin_checksum.py +4 -1
- ruyi/ruyipkg/admin_cli.py +9 -6
- ruyi/ruyipkg/augmented_pkg.py +15 -14
- ruyi/ruyipkg/checksum.py +8 -2
- ruyi/ruyipkg/distfile.py +33 -9
- ruyi/ruyipkg/entity.py +12 -2
- ruyi/ruyipkg/entity_cli.py +20 -12
- ruyi/ruyipkg/entity_provider.py +11 -2
- ruyi/ruyipkg/fetcher.py +38 -9
- ruyi/ruyipkg/install.py +163 -64
- ruyi/ruyipkg/install_cli.py +18 -15
- ruyi/ruyipkg/list.py +27 -20
- ruyi/ruyipkg/list_cli.py +12 -7
- ruyi/ruyipkg/news.py +23 -11
- ruyi/ruyipkg/news_cli.py +10 -7
- ruyi/ruyipkg/profile_cli.py +8 -2
- ruyi/ruyipkg/repo.py +22 -8
- ruyi/ruyipkg/unpack.py +42 -8
- ruyi/ruyipkg/unpack_method.py +5 -1
- ruyi/ruyipkg/update_cli.py +8 -3
- ruyi/telemetry/aggregate.py +5 -0
- ruyi/telemetry/provider.py +292 -105
- ruyi/telemetry/store.py +68 -15
- ruyi/telemetry/telemetry_cli.py +32 -13
- ruyi/utils/git.py +18 -11
- ruyi/utils/prereqs.py +10 -5
- ruyi/utils/ssl_patch.py +2 -1
- ruyi/version.py +9 -3
- {ruyi-0.44.0a20251118.dist-info → ruyi-0.45.0.dist-info}/METADATA +4 -2
- ruyi-0.45.0.dist-info/RECORD +103 -0
- {ruyi-0.44.0a20251118.dist-info → ruyi-0.45.0.dist-info}/WHEEL +1 -1
- ruyi-0.44.0a20251118.dist-info/RECORD +0 -102
- {ruyi-0.44.0a20251118.dist-info → ruyi-0.45.0.dist-info}/entry_points.txt +0 -0
- {ruyi-0.44.0a20251118.dist-info → ruyi-0.45.0.dist-info}/licenses/LICENSE-Apache.txt +0 -0
ruyi/mux/runtime.py
CHANGED
|
@@ -5,6 +5,7 @@ import shlex
|
|
|
5
5
|
from typing import Final, List, NoReturn
|
|
6
6
|
|
|
7
7
|
from ..config import GlobalConfig
|
|
8
|
+
from ..i18n import _
|
|
8
9
|
from ..utils.global_mode import ProvidesGlobalMode
|
|
9
10
|
from .venv_cfg import RuyiVenvConfig
|
|
10
11
|
|
|
@@ -31,8 +32,8 @@ def mux_main(
|
|
|
31
32
|
|
|
32
33
|
vcfg = RuyiVenvConfig.load_from_venv(gm, logger)
|
|
33
34
|
if vcfg is None:
|
|
34
|
-
logger.F("the Ruyi toolchain mux is not configured")
|
|
35
|
-
logger.I("check out `ruyi venv` for making a virtual environment")
|
|
35
|
+
logger.F(_("the Ruyi toolchain mux is not configured"))
|
|
36
|
+
logger.I(_("check out `ruyi venv` for making a virtual environment"))
|
|
36
37
|
return 1
|
|
37
38
|
|
|
38
39
|
direct_symlink_target = resolve_direct_symlink_target(gm.argv0, vcfg)
|
|
@@ -60,7 +61,11 @@ def mux_main(
|
|
|
60
61
|
tgt_data = vcfg.targets.get(target_tuple)
|
|
61
62
|
if tgt_data is None:
|
|
62
63
|
logger.F(
|
|
63
|
-
|
|
64
|
+
_(
|
|
65
|
+
"internal error: no target data for tuple [yellow]{target_tuple}[/]"
|
|
66
|
+
).format(
|
|
67
|
+
target_tuple=target_tuple,
|
|
68
|
+
)
|
|
64
69
|
)
|
|
65
70
|
return 1
|
|
66
71
|
toolchain_sysroot = tgt_data.get("toolchain_sysroot")
|
|
@@ -83,14 +88,22 @@ def mux_main(
|
|
|
83
88
|
if toolchain_bindir is None:
|
|
84
89
|
# should not happen
|
|
85
90
|
logger.F(
|
|
86
|
-
|
|
91
|
+
_(
|
|
92
|
+
"internal error: no bindir configured for target [yellow]{target_tuple}[/]"
|
|
93
|
+
).format(
|
|
94
|
+
target_tuple=target_tuple,
|
|
95
|
+
)
|
|
87
96
|
)
|
|
88
97
|
return 1
|
|
89
98
|
|
|
90
99
|
binpath = os.path.join(toolchain_bindir, basename)
|
|
91
100
|
|
|
92
101
|
if target_tuple is None:
|
|
93
|
-
logger.F(
|
|
102
|
+
logger.F(
|
|
103
|
+
_("no configured target found for command [yellow]{basename}[/]").format(
|
|
104
|
+
basename=basename,
|
|
105
|
+
)
|
|
106
|
+
)
|
|
94
107
|
return 1
|
|
95
108
|
|
|
96
109
|
logger.D(f"binary to exec: {binpath}")
|
|
@@ -176,7 +189,7 @@ def mux_qemu_main(
|
|
|
176
189
|
logger = gc.logger
|
|
177
190
|
binpath = vcfg.qemu_bin
|
|
178
191
|
if binpath is None:
|
|
179
|
-
logger.F("this virtual environment has no QEMU-like emulator configured")
|
|
192
|
+
logger.F(_("this virtual environment has no QEMU-like emulator configured"))
|
|
180
193
|
return 1
|
|
181
194
|
|
|
182
195
|
if vcfg.profile_emu_env is not None:
|
ruyi/mux/venv/maker.py
CHANGED
|
@@ -7,11 +7,13 @@ import shutil
|
|
|
7
7
|
from typing import Any, Final, Iterator, TypedDict
|
|
8
8
|
|
|
9
9
|
from ...config import GlobalConfig
|
|
10
|
+
from ...i18n import _
|
|
10
11
|
from ...log import RuyiLogger, humanize_list
|
|
11
12
|
from ...ruyipkg.atom import Atom
|
|
12
13
|
from ...ruyipkg.pkg_manifest import BoundPackageManifest, EmulatorProgDecl
|
|
13
14
|
from ...ruyipkg.profile import ProfileProxy
|
|
14
15
|
from ...utils.global_mode import ProvidesGlobalMode
|
|
16
|
+
from ...utils.l10n import match_lang_code
|
|
15
17
|
from ...utils.templating import render_template_str
|
|
16
18
|
from .emulator_cfg import ResolvedEmulatorProg
|
|
17
19
|
|
|
@@ -67,7 +69,7 @@ def do_make_venv(
|
|
|
67
69
|
# this should come after implementation of local state cache
|
|
68
70
|
if tc_atoms_str is None:
|
|
69
71
|
logger.F(
|
|
70
|
-
"You have to specify at least one toolchain atom for now, e.g. [yellow]`-t gnu-plct`[/]"
|
|
72
|
+
_("You have to specify at least one toolchain atom for now, e.g. [yellow]`-t gnu-plct`[/]")
|
|
71
73
|
)
|
|
72
74
|
return 1
|
|
73
75
|
|
|
@@ -75,7 +77,7 @@ def do_make_venv(
|
|
|
75
77
|
|
|
76
78
|
profile = mr.get_profile(profile_name)
|
|
77
79
|
if profile is None:
|
|
78
|
-
logger.F(
|
|
80
|
+
logger.F(_("profile '{profile}' not found").format(profile=profile_name))
|
|
79
81
|
return 1
|
|
80
82
|
|
|
81
83
|
target_arch = ""
|
|
@@ -93,32 +95,46 @@ def do_make_venv(
|
|
|
93
95
|
tc_atom = Atom.parse(tc_atom_str)
|
|
94
96
|
tc_pm = tc_atom.match_in_repo(mr, config.include_prereleases)
|
|
95
97
|
if tc_pm is None:
|
|
96
|
-
logger.F(
|
|
98
|
+
logger.F(_("cannot match a toolchain package with [yellow]{atom}[/]").format(
|
|
99
|
+
atom=tc_atom_str,
|
|
100
|
+
))
|
|
97
101
|
return 1
|
|
98
102
|
|
|
99
103
|
if tc_pm.toolchain_metadata is None:
|
|
100
|
-
logger.F(
|
|
104
|
+
logger.F(_("the package [yellow]{atom}[/] is not a toolchain").format(
|
|
105
|
+
atom=tc_atom_str,
|
|
106
|
+
))
|
|
101
107
|
return 1
|
|
102
108
|
|
|
103
109
|
if not tc_pm.toolchain_metadata.satisfies_quirk_set(profile.need_quirks):
|
|
104
|
-
logger.F(
|
|
105
|
-
|
|
110
|
+
logger.F(_(
|
|
111
|
+
"the package [yellow]{atom}[/] does not support all necessary features for the profile [yellow]{profile}[/]"
|
|
112
|
+
).format(
|
|
113
|
+
atom=tc_atom_str,
|
|
114
|
+
profile=profile_name,
|
|
115
|
+
)
|
|
106
116
|
)
|
|
107
117
|
logger.I(
|
|
108
|
-
|
|
118
|
+
_("quirks needed by profile: {humanized_list}").format(
|
|
119
|
+
humanized_list=humanize_list(profile.need_quirks, item_color='cyan'),
|
|
120
|
+
)
|
|
109
121
|
)
|
|
110
122
|
logger.I(
|
|
111
|
-
|
|
123
|
+
_("quirks provided by package: {humanized_list}").format(
|
|
124
|
+
humanized_list=humanize_list(tc_pm.toolchain_metadata.quirks, item_color='yellow'),
|
|
125
|
+
)
|
|
112
126
|
)
|
|
113
127
|
return 1
|
|
114
128
|
|
|
115
129
|
target_tuple = tc_pm.toolchain_metadata.target
|
|
116
130
|
if target_tuple in seen_target_tuples:
|
|
117
131
|
logger.F(
|
|
118
|
-
|
|
132
|
+
_("the target tuple [yellow]{target_tuple}[/] is already covered by one of the requested toolchains").format(
|
|
133
|
+
target_tuple=target_tuple,
|
|
134
|
+
)
|
|
119
135
|
)
|
|
120
136
|
logger.I(
|
|
121
|
-
"for now, only toolchains with differing target tuples can co-exist in one virtual environment"
|
|
137
|
+
_("for now, only toolchains with differing target tuples can co-exist in one virtual environment")
|
|
122
138
|
)
|
|
123
139
|
return 1
|
|
124
140
|
|
|
@@ -127,7 +143,7 @@ def do_make_venv(
|
|
|
127
143
|
tc_pm.name_for_installation,
|
|
128
144
|
)
|
|
129
145
|
if toolchain_root is None:
|
|
130
|
-
logger.F("cannot find the installed directory for the toolchain")
|
|
146
|
+
logger.F(_("cannot find the installed directory for the toolchain"))
|
|
131
147
|
return 1
|
|
132
148
|
|
|
133
149
|
tc_sysroot_dir: PathLike[Any] | None = None
|
|
@@ -139,7 +155,7 @@ def do_make_venv(
|
|
|
139
155
|
else:
|
|
140
156
|
if sysroot_atom_str is None:
|
|
141
157
|
logger.F(
|
|
142
|
-
"sysroot is requested but the toolchain package does not include one, and [yellow]--sysroot-from[/] is not given"
|
|
158
|
+
_("sysroot is requested but the toolchain package does not include one, and [yellow]--sysroot-from[/] is not given")
|
|
143
159
|
)
|
|
144
160
|
return 1
|
|
145
161
|
|
|
@@ -150,13 +166,17 @@ def do_make_venv(
|
|
|
150
166
|
gcc_pkg_pm = gcc_pkg_atom.match_in_repo(mr, config.include_prereleases)
|
|
151
167
|
if gcc_pkg_pm is None:
|
|
152
168
|
logger.F(
|
|
153
|
-
|
|
169
|
+
_("cannot match a toolchain package with [yellow]{atom}[/]").format(
|
|
170
|
+
atom=sysroot_atom_str,
|
|
171
|
+
)
|
|
154
172
|
)
|
|
155
173
|
return 1
|
|
156
174
|
|
|
157
175
|
if gcc_pkg_pm.toolchain_metadata is None:
|
|
158
176
|
logger.F(
|
|
159
|
-
|
|
177
|
+
_("the package [yellow]{atom}[/] is not a toolchain").format(
|
|
178
|
+
atom=sysroot_atom_str,
|
|
179
|
+
)
|
|
160
180
|
)
|
|
161
181
|
return 1
|
|
162
182
|
|
|
@@ -166,14 +186,16 @@ def do_make_venv(
|
|
|
166
186
|
)
|
|
167
187
|
if gcc_pkg_root is None:
|
|
168
188
|
logger.F(
|
|
169
|
-
"cannot find the installed directory for the sysroot package"
|
|
189
|
+
_("cannot find the installed directory for the sysroot package")
|
|
170
190
|
)
|
|
171
191
|
return 1
|
|
172
192
|
|
|
173
193
|
tc_sysroot_relpath = gcc_pkg_pm.toolchain_metadata.included_sysroot
|
|
174
194
|
if tc_sysroot_relpath is None:
|
|
175
195
|
logger.F(
|
|
176
|
-
|
|
196
|
+
_("sysroot is requested but the package [yellow]{atom}[/] does not contain one").format(
|
|
197
|
+
atom=sysroot_atom_str,
|
|
198
|
+
)
|
|
177
199
|
)
|
|
178
200
|
return 1
|
|
179
201
|
|
|
@@ -191,7 +213,7 @@ def do_make_venv(
|
|
|
191
213
|
# for now, require this directory to be present (or clang would barely work)
|
|
192
214
|
if gcc_install_dir is None:
|
|
193
215
|
logger.F(
|
|
194
|
-
"cannot find a GCC include & lib directory in the sysroot package"
|
|
216
|
+
_("cannot find a GCC include & lib directory in the sysroot package")
|
|
195
217
|
)
|
|
196
218
|
return 1
|
|
197
219
|
|
|
@@ -228,9 +250,11 @@ def do_make_venv(
|
|
|
228
250
|
warn_differing_target_arch = True
|
|
229
251
|
|
|
230
252
|
if warn_differing_target_arch:
|
|
231
|
-
logger.W("multiple toolchains specified with differing target architecture")
|
|
253
|
+
logger.W(_("multiple toolchains specified with differing target architecture"))
|
|
232
254
|
logger.I(
|
|
233
|
-
|
|
255
|
+
_("using the target architecture of the first toolchain: [yellow]{arch}[/]").format(
|
|
256
|
+
arch=target_arch,
|
|
257
|
+
)
|
|
234
258
|
)
|
|
235
259
|
|
|
236
260
|
# Now handle the emulator.
|
|
@@ -240,17 +264,24 @@ def do_make_venv(
|
|
|
240
264
|
emu_atom = Atom.parse(emu_atom_str)
|
|
241
265
|
emu_pm = emu_atom.match_in_repo(mr, config.include_prereleases)
|
|
242
266
|
if emu_pm is None:
|
|
243
|
-
logger.F(
|
|
267
|
+
logger.F(_("cannot match an emulator package with [yellow]{atom}[/]").format(
|
|
268
|
+
atom=emu_atom_str,
|
|
269
|
+
))
|
|
244
270
|
return 1
|
|
245
271
|
|
|
246
272
|
if emu_pm.emulator_metadata is None:
|
|
247
|
-
logger.F(
|
|
273
|
+
logger.F(_("the package [yellow]{atom}[/] is not an emulator").format(
|
|
274
|
+
atom=emu_atom_str,
|
|
275
|
+
))
|
|
248
276
|
return 1
|
|
249
277
|
|
|
250
278
|
emu_progs = list(emu_pm.emulator_metadata.list_for_arch(target_arch))
|
|
251
279
|
if not emu_progs:
|
|
252
280
|
logger.F(
|
|
253
|
-
|
|
281
|
+
_("the emulator package [yellow]{atom}[/] does not support the target architecture [yellow]{arch}[/]").format(
|
|
282
|
+
atom=emu_atom_str,
|
|
283
|
+
arch=target_arch,
|
|
284
|
+
)
|
|
254
285
|
)
|
|
255
286
|
return 1
|
|
256
287
|
|
|
@@ -260,13 +291,20 @@ def do_make_venv(
|
|
|
260
291
|
emu_pm.emulator_metadata.quirks,
|
|
261
292
|
):
|
|
262
293
|
logger.F(
|
|
263
|
-
|
|
294
|
+
_("the package [yellow]{atom}[/] does not support all necessary features for the profile [yellow]{profile}[/]").format(
|
|
295
|
+
atom=emu_atom_str,
|
|
296
|
+
profile=profile_name,
|
|
297
|
+
)
|
|
264
298
|
)
|
|
265
299
|
logger.I(
|
|
266
|
-
|
|
300
|
+
_("quirks needed by profile: {humanized_list}").format(
|
|
301
|
+
humanized_list=humanize_list(profile.get_needed_emulator_pkg_flavors(prog.flavor), item_color='cyan'),
|
|
302
|
+
)
|
|
267
303
|
)
|
|
268
304
|
logger.I(
|
|
269
|
-
|
|
305
|
+
_("quirks provided by package: {humanized_list}").format(
|
|
306
|
+
humanized_list=humanize_list(emu_pm.emulator_metadata.quirks or [], item_color='yellow'),
|
|
307
|
+
)
|
|
270
308
|
)
|
|
271
309
|
return 1
|
|
272
310
|
|
|
@@ -275,7 +313,7 @@ def do_make_venv(
|
|
|
275
313
|
emu_pm.name_for_installation,
|
|
276
314
|
)
|
|
277
315
|
if emu_root is None:
|
|
278
|
-
logger.F("cannot find the installed directory for the emulator")
|
|
316
|
+
logger.F(_("cannot find the installed directory for the emulator"))
|
|
279
317
|
return 1
|
|
280
318
|
|
|
281
319
|
venv_metadata["emulator_pkgs"][target_arch] = _venv_pkg_info_from_pkg(emu_pm)
|
|
@@ -291,21 +329,28 @@ def do_make_venv(
|
|
|
291
329
|
)
|
|
292
330
|
if extra_cmd_pm is None:
|
|
293
331
|
logger.F(
|
|
294
|
-
|
|
332
|
+
_("cannot match an extra command package with [yellow]{atom}[/]").format(
|
|
333
|
+
atom=extra_cmd_atom_str,
|
|
334
|
+
)
|
|
295
335
|
)
|
|
296
336
|
return 1
|
|
297
337
|
|
|
298
338
|
extra_cmd_bm = extra_cmd_pm.binary_metadata
|
|
299
339
|
if not extra_cmd_bm:
|
|
300
340
|
logger.F(
|
|
301
|
-
|
|
341
|
+
_("the package [yellow]{atom}[/] is not a binary-providing package").format(
|
|
342
|
+
atom=extra_cmd_atom_str,
|
|
343
|
+
)
|
|
302
344
|
)
|
|
303
345
|
return 1
|
|
304
346
|
|
|
305
347
|
extra_cmds_decl = extra_cmd_bm.get_commands_for_host(host)
|
|
306
348
|
if not extra_cmds_decl:
|
|
307
349
|
logger.W(
|
|
308
|
-
|
|
350
|
+
_("the package [yellow]{atom}[/] does not provide any command for host [yellow]{host}[/], ignoring").format(
|
|
351
|
+
atom=extra_cmd_atom_str,
|
|
352
|
+
host=host,
|
|
353
|
+
)
|
|
309
354
|
)
|
|
310
355
|
continue
|
|
311
356
|
|
|
@@ -315,7 +360,9 @@ def do_make_venv(
|
|
|
315
360
|
)
|
|
316
361
|
if cmd_root is None:
|
|
317
362
|
logger.F(
|
|
318
|
-
|
|
363
|
+
_("cannot find the installed directory for the package [yellow]{pkg}[/]").format(
|
|
364
|
+
pkg=extra_cmd_pm.name_for_installation,
|
|
365
|
+
)
|
|
319
366
|
)
|
|
320
367
|
return 1
|
|
321
368
|
cmd_root = pathlib.Path(cmd_root)
|
|
@@ -329,7 +376,7 @@ def do_make_venv(
|
|
|
329
376
|
# we don't allow commands to resolve outside of the
|
|
330
377
|
# providing package's install root
|
|
331
378
|
logger.F(
|
|
332
|
-
"internal error: resolved command path is outside of the providing package"
|
|
379
|
+
_("internal error: resolved command path is outside of the providing package")
|
|
333
380
|
)
|
|
334
381
|
return 1
|
|
335
382
|
|
|
@@ -338,10 +385,17 @@ def do_make_venv(
|
|
|
338
385
|
|
|
339
386
|
if override_name is not None:
|
|
340
387
|
logger.I(
|
|
341
|
-
|
|
388
|
+
_("Creating a Ruyi virtual environment [cyan]'{name}'[/] at [green]{dest}[/]...").format(
|
|
389
|
+
name=override_name,
|
|
390
|
+
dest=dest,
|
|
391
|
+
)
|
|
342
392
|
)
|
|
343
393
|
else:
|
|
344
|
-
logger.I(
|
|
394
|
+
logger.I(
|
|
395
|
+
_("Creating a Ruyi virtual environment at [green]{dest}[/]...").format(
|
|
396
|
+
dest=dest,
|
|
397
|
+
)
|
|
398
|
+
)
|
|
345
399
|
|
|
346
400
|
maker = VenvMaker(
|
|
347
401
|
config,
|
|
@@ -356,9 +410,11 @@ def do_make_venv(
|
|
|
356
410
|
)
|
|
357
411
|
maker.provision()
|
|
358
412
|
|
|
413
|
+
# TODO: move the template to PO
|
|
414
|
+
locale = match_lang_code(config.lang_code, avail=("en", "zh_CN"))
|
|
359
415
|
logger.I(
|
|
360
416
|
render_template_str(
|
|
361
|
-
"prompt.venv-created.txt",
|
|
417
|
+
f"prompt.venv-created.{locale}.txt",
|
|
362
418
|
{
|
|
363
419
|
"sysroot": maker.sysroot_destdir(None),
|
|
364
420
|
},
|
|
@@ -559,7 +615,9 @@ class VenvMaker:
|
|
|
559
615
|
for cmd, dest in extra_cmds.items():
|
|
560
616
|
if cmd in cmd_metadata_map:
|
|
561
617
|
self.logger.W(
|
|
562
|
-
|
|
618
|
+
_("extra command {cmd} is already provided by another package, overriding it").format(
|
|
619
|
+
cmd=cmd,
|
|
620
|
+
)
|
|
563
621
|
)
|
|
564
622
|
cmd_metadata_map[cmd] = {
|
|
565
623
|
"dest": dest,
|
ruyi/mux/venv/venv_cli.py
CHANGED
|
@@ -3,6 +3,7 @@ import pathlib
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from ...cli.cmd import RootCommand
|
|
6
|
+
from ...i18n import _
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from ...cli.completion import ArgumentParser
|
|
@@ -12,55 +13,57 @@ if TYPE_CHECKING:
|
|
|
12
13
|
class VenvCommand(
|
|
13
14
|
RootCommand,
|
|
14
15
|
cmd="venv",
|
|
15
|
-
help="Generate a virtual environment adapted to the chosen toolchain and profile",
|
|
16
|
+
help=_("Generate a virtual environment adapted to the chosen toolchain and profile"),
|
|
16
17
|
):
|
|
17
18
|
@classmethod
|
|
18
19
|
def configure_args(cls, gc: "GlobalConfig", p: "ArgumentParser") -> None:
|
|
19
|
-
p.add_argument("profile", type=str, help="Profile to use for the environment")
|
|
20
|
-
|
|
20
|
+
p.add_argument("profile", type=str, help=_("Profile to use for the environment"),
|
|
21
|
+
)
|
|
22
|
+
p.add_argument("dest", type=str, help=_("Path to the new virtual environment"),
|
|
23
|
+
)
|
|
21
24
|
p.add_argument(
|
|
22
25
|
"--name",
|
|
23
26
|
"-n",
|
|
24
27
|
type=str,
|
|
25
28
|
default=None,
|
|
26
|
-
help="Override the venv's name",
|
|
29
|
+
help=_("Override the venv's name"),
|
|
27
30
|
)
|
|
28
31
|
p.add_argument(
|
|
29
32
|
"--toolchain",
|
|
30
33
|
"-t",
|
|
31
34
|
type=str,
|
|
32
35
|
action="append",
|
|
33
|
-
help="Specifier(s) (atoms) of the toolchain package(s) to use",
|
|
36
|
+
help=_("Specifier(s) (atoms) of the toolchain package(s) to use"),
|
|
34
37
|
)
|
|
35
38
|
p.add_argument(
|
|
36
39
|
"--emulator",
|
|
37
40
|
"-e",
|
|
38
41
|
type=str,
|
|
39
|
-
help="Specifier (atom) of the emulator package to use",
|
|
42
|
+
help=_("Specifier (atom) of the emulator package to use"),
|
|
40
43
|
)
|
|
41
44
|
p.add_argument(
|
|
42
45
|
"--with-sysroot",
|
|
43
46
|
action="store_true",
|
|
44
47
|
dest="with_sysroot",
|
|
45
48
|
default=True,
|
|
46
|
-
help="Provision a fresh sysroot inside the new virtual environment (default)",
|
|
49
|
+
help=_("Provision a fresh sysroot inside the new virtual environment (default)"),
|
|
47
50
|
)
|
|
48
51
|
p.add_argument(
|
|
49
52
|
"--without-sysroot",
|
|
50
53
|
action="store_false",
|
|
51
54
|
dest="with_sysroot",
|
|
52
|
-
help="Do not include a sysroot inside the new virtual environment",
|
|
55
|
+
help=_("Do not include a sysroot inside the new virtual environment"),
|
|
53
56
|
)
|
|
54
57
|
p.add_argument(
|
|
55
58
|
"--sysroot-from",
|
|
56
59
|
type=str,
|
|
57
|
-
help="Specifier (atom) of the sysroot package to use, in favor of the toolchain-included one if applicable",
|
|
60
|
+
help=_("Specifier (atom) of the sysroot package to use, in favor of the toolchain-included one if applicable"),
|
|
58
61
|
)
|
|
59
62
|
p.add_argument(
|
|
60
63
|
"--extra-commands-from",
|
|
61
64
|
type=str,
|
|
62
65
|
action="append",
|
|
63
|
-
help="Specifier(s) (atoms) of extra package(s) to add commands to the new virtual environment",
|
|
66
|
+
help=_("Specifier(s) (atoms) of extra package(s) to add commands to the new virtual environment"),
|
|
64
67
|
)
|
|
65
68
|
|
|
66
69
|
@classmethod
|
ruyi/pluginhost/plugin_cli.py
CHANGED
|
@@ -2,6 +2,7 @@ import argparse
|
|
|
2
2
|
from typing import TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
from ..cli.cmd import AdminCommand
|
|
5
|
+
from ..i18n import _
|
|
5
6
|
|
|
6
7
|
if TYPE_CHECKING:
|
|
7
8
|
from ..cli.completion import ArgumentParser
|
|
@@ -11,7 +12,7 @@ if TYPE_CHECKING:
|
|
|
11
12
|
class AdminRunPluginCommand(
|
|
12
13
|
AdminCommand,
|
|
13
14
|
cmd="run-plugin-cmd",
|
|
14
|
-
help="Run a plugin-defined command",
|
|
15
|
+
help=_("Run a plugin-defined command"),
|
|
15
16
|
):
|
|
16
17
|
@classmethod
|
|
17
18
|
def configure_args(cls, gc: "GlobalConfig", p: "ArgumentParser") -> None:
|
|
@@ -19,14 +20,14 @@ class AdminRunPluginCommand(
|
|
|
19
20
|
"cmd_name",
|
|
20
21
|
type=str,
|
|
21
22
|
metavar="COMMAND-NAME",
|
|
22
|
-
help="Command name",
|
|
23
|
+
help=_("Command name"),
|
|
23
24
|
)
|
|
24
25
|
p.add_argument(
|
|
25
26
|
"cmd_args",
|
|
26
27
|
type=str,
|
|
27
28
|
nargs="*",
|
|
28
29
|
metavar="COMMAND-ARG",
|
|
29
|
-
help="Arguments to pass to the plugin command",
|
|
30
|
+
help=_("Arguments to pass to the plugin command"),
|
|
30
31
|
)
|
|
31
32
|
|
|
32
33
|
@classmethod
|
ruyi/resource_bundle/__init__.py
CHANGED
|
@@ -1,20 +1,34 @@
|
|
|
1
1
|
import base64
|
|
2
2
|
import zlib
|
|
3
3
|
|
|
4
|
-
from .data import RESOURCES,
|
|
4
|
+
from .data import RESOURCES, TEMPLATE_NAME_MAP
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
def _unpack_payload(x: bytes) ->
|
|
8
|
-
return zlib.decompress(base64.b64decode(x))
|
|
7
|
+
def _unpack_payload(x: bytes) -> bytes:
|
|
8
|
+
return zlib.decompress(base64.b64decode(x))
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
_CACHE: dict[str, bytes] = {}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_resource_blob(name: str) -> bytes | None:
|
|
15
|
+
if t := RESOURCES.get(name):
|
|
16
|
+
if name not in _CACHE:
|
|
17
|
+
# In our use cases, the program is short-lived and involved resources
|
|
18
|
+
# are small in size, so it is fine to just store the decompressed
|
|
19
|
+
# blobs without eviction.
|
|
20
|
+
_CACHE[name] = _unpack_payload(t)
|
|
21
|
+
return _CACHE[name]
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_resource_str(name: str) -> str | None:
|
|
26
|
+
if blob := get_resource_blob(name):
|
|
27
|
+
return blob.decode("utf-8")
|
|
14
28
|
return None
|
|
15
29
|
|
|
16
30
|
|
|
17
31
|
def get_template_str(template_name: str) -> str | None:
|
|
18
|
-
if t :=
|
|
19
|
-
return
|
|
32
|
+
if t := TEMPLATE_NAME_MAP.get(template_name):
|
|
33
|
+
return get_resource_str(t)
|
|
20
34
|
return None
|
ruyi/resource_bundle/__main__.py
CHANGED
|
@@ -20,15 +20,16 @@ def main() -> None:
|
|
|
20
20
|
|
|
21
21
|
resources: dict[str, str] = {}
|
|
22
22
|
template_names: dict[str, str] = {}
|
|
23
|
-
for f in bundled_resource_root.
|
|
23
|
+
for f in bundled_resource_root.glob("**/*"):
|
|
24
24
|
if not f.is_file():
|
|
25
25
|
continue
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
rel_path = f.relative_to(bundled_resource_root)
|
|
28
|
+
resources[str(rel_path)] = make_payload_from_file(f)
|
|
28
29
|
|
|
29
30
|
if f.suffix.lower() == ".jinja":
|
|
30
31
|
# strip the .jinja suffix for the template name
|
|
31
|
-
template_names[
|
|
32
|
+
template_names[str(rel_path.with_suffix(""))] = str(rel_path)
|
|
32
33
|
|
|
33
34
|
with open(self_path / "data.py", "w", encoding="utf-8") as fp:
|
|
34
35
|
|
|
@@ -45,9 +46,9 @@ def main() -> None:
|
|
|
45
46
|
p(f' "{filename}": b"{payload}", # fmt: skip')
|
|
46
47
|
p("}\n")
|
|
47
48
|
|
|
48
|
-
p("
|
|
49
|
+
p("TEMPLATE_NAME_MAP: Final = {")
|
|
49
50
|
for stem, full_filename in sorted(template_names.items()):
|
|
50
|
-
p(f' "{stem}":
|
|
51
|
+
p(f' "{stem}": "{full_filename}",')
|
|
51
52
|
p("}")
|
|
52
53
|
|
|
53
54
|
|