ruyi 0.42.0b20251015__tar.gz → 0.43.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.
Files changed (103) hide show
  1. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/PKG-INFO +4 -3
  2. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/pyproject.toml +4 -3
  3. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/__main__.py +4 -0
  4. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/cli/main.py +6 -1
  5. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/cli/oobe.py +1 -1
  6. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/mux/venv/maker.py +52 -2
  7. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/pluginhost/api.py +1 -1
  8. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/pluginhost/unsandboxed.py +1 -1
  9. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/resource_bundle/data.py +1 -1
  10. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/telemetry/aggregate.py +1 -1
  11. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/telemetry/provider.py +1 -1
  12. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/telemetry/store.py +2 -2
  13. ruyi-0.43.0/ruyi/utils/__init__.py +0 -0
  14. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/global_mode.py +1 -1
  15. {ruyi-0.42.0b20251015/ruyi/telemetry → ruyi-0.43.0/ruyi/utils}/node_info.py +52 -1
  16. ruyi-0.43.0/ruyi/version.py +20 -0
  17. ruyi-0.42.0b20251015/ruyi/mux/venv/__init__.py +0 -12
  18. ruyi-0.42.0b20251015/ruyi/version.py +0 -67
  19. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/LICENSE-Apache.txt +0 -0
  20. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/README.md +0 -0
  21. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/__init__.py +0 -0
  22. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/cli/__init__.py +0 -0
  23. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/cli/builtin_commands.py +0 -0
  24. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/cli/cmd.py +0 -0
  25. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/cli/completer.py +0 -0
  26. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/cli/completion.py +0 -0
  27. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/cli/config_cli.py +0 -0
  28. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/cli/self_cli.py +0 -0
  29. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/cli/user_input.py +0 -0
  30. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/cli/version_cli.py +0 -0
  31. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/config/__init__.py +0 -0
  32. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/config/editor.py +0 -0
  33. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/config/errors.py +0 -0
  34. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/config/news.py +0 -0
  35. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/config/schema.py +0 -0
  36. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/device/__init__.py +0 -0
  37. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/device/provision.py +0 -0
  38. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/device/provision_cli.py +0 -0
  39. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/log/__init__.py +0 -0
  40. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/mux/__init__.py +0 -0
  41. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/mux/runtime.py +0 -0
  42. {ruyi-0.42.0b20251015/ruyi/pluginhost → ruyi-0.43.0/ruyi/mux/venv}/__init__.py +0 -0
  43. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/mux/venv/emulator_cfg.py +0 -0
  44. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/mux/venv/venv_cli.py +0 -0
  45. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/mux/venv_cfg.py +0 -0
  46. {ruyi-0.42.0b20251015/ruyi/ruyipkg → ruyi-0.43.0/ruyi/pluginhost}/__init__.py +0 -0
  47. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/pluginhost/ctx.py +0 -0
  48. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/pluginhost/paths.py +0 -0
  49. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/pluginhost/plugin_cli.py +0 -0
  50. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/py.typed +0 -0
  51. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/resource_bundle/__init__.py +0 -0
  52. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/resource_bundle/__main__.py +0 -0
  53. {ruyi-0.42.0b20251015/ruyi/telemetry → ruyi-0.43.0/ruyi/ruyipkg}/__init__.py +0 -0
  54. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/admin_checksum.py +0 -0
  55. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/admin_cli.py +0 -0
  56. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/atom.py +0 -0
  57. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/augmented_pkg.py +0 -0
  58. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/canonical_dump.py +0 -0
  59. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/checksum.py +0 -0
  60. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/cli_completion.py +0 -0
  61. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/distfile.py +0 -0
  62. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/entity.py +0 -0
  63. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/entity_cli.py +0 -0
  64. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/entity_provider.py +0 -0
  65. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/fetcher.py +0 -0
  66. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/host.py +0 -0
  67. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/install.py +0 -0
  68. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/install_cli.py +0 -0
  69. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/list.py +0 -0
  70. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/list_cli.py +0 -0
  71. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/list_filter.py +0 -0
  72. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/msg.py +0 -0
  73. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/news.py +0 -0
  74. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/news_cli.py +0 -0
  75. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/news_store.py +0 -0
  76. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/pkg_manifest.py +0 -0
  77. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/profile.py +0 -0
  78. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/profile_cli.py +0 -0
  79. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/protocols.py +0 -0
  80. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/repo.py +0 -0
  81. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/state.py +0 -0
  82. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/unpack.py +0 -0
  83. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/unpack_method.py +0 -0
  84. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/ruyipkg/update_cli.py +0 -0
  85. {ruyi-0.42.0b20251015/ruyi/utils → ruyi-0.43.0/ruyi/telemetry}/__init__.py +0 -0
  86. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/telemetry/event.py +0 -0
  87. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/telemetry/scope.py +0 -0
  88. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/telemetry/telemetry_cli.py +0 -0
  89. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/ar.py +0 -0
  90. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/ci.py +0 -0
  91. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/frontmatter.py +0 -0
  92. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/git.py +0 -0
  93. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/l10n.py +0 -0
  94. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/markdown.py +0 -0
  95. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/mounts.py +0 -0
  96. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/nuitka.py +0 -0
  97. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/porcelain.py +0 -0
  98. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/prereqs.py +0 -0
  99. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/ssl_patch.py +0 -0
  100. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/templating.py +0 -0
  101. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/toml.py +0 -0
  102. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/url.py +0 -0
  103. {ruyi-0.42.0b20251015 → ruyi-0.43.0}/ruyi/utils/xdg_basedir.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ruyi
3
- Version: 0.42.0b20251015
3
+ Version: 0.43.0
4
4
  Summary: Package manager for RuyiSDK
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -217,6 +217,7 @@ Classifier: Programming Language :: Python :: 3.10
217
217
  Classifier: Programming Language :: Python :: 3.11
218
218
  Classifier: Programming Language :: Python :: 3.12
219
219
  Classifier: Programming Language :: Python :: 3.13
220
+ Classifier: Programming Language :: Python :: 3.14
220
221
  Classifier: Topic :: Software Development :: Build Tools
221
222
  Classifier: Topic :: Software Development :: Embedded Systems
222
223
  Classifier: Topic :: System :: Software Distribution
@@ -225,8 +226,8 @@ Requires-Dist: argcomplete (>=2.0.0)
225
226
  Requires-Dist: arpy
226
227
  Requires-Dist: fastjsonschema (>=2.15.1)
227
228
  Requires-Dist: jinja2 (>=3,<4)
228
- Requires-Dist: packaging (>=21)
229
- Requires-Dist: pygit2 (>=1.6)
229
+ Requires-Dist: pygit2 (>=1.6) ; python_version >= "3.11"
230
+ Requires-Dist: pygit2 (>=1.6,<1.19) ; python_version < "3.11"
230
231
  Requires-Dist: pyyaml (>=5.4)
231
232
  Requires-Dist: requests (>=2,<3)
232
233
  Requires-Dist: rich (>=11.2.0)
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [project]
6
6
  name = "ruyi"
7
- version = "0.42.0-beta.20251015"
7
+ version = "0.43.0"
8
8
  description = "Package manager for RuyiSDK"
9
9
  keywords = ["ruyi", "ruyisdk"]
10
10
  license = { file = "LICENSE-Apache.txt" }
@@ -22,6 +22,7 @@ classifiers = [
22
22
  "Programming Language :: Python :: 3.11",
23
23
  "Programming Language :: Python :: 3.12",
24
24
  "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: 3.14",
25
26
  "Topic :: Software Development :: Build Tools",
26
27
  "Topic :: Software Development :: Embedded Systems",
27
28
  "Topic :: System :: Software Distribution",
@@ -33,8 +34,8 @@ dependencies = [
33
34
  "arpy",
34
35
  "fastjsonschema>=2.15.1",
35
36
  "jinja2 (>=3, <4)",
36
- "packaging>=21",
37
- "pygit2>=1.6",
37
+ "pygit2 (>=1.6, <1.19); python_version<'3.11'",
38
+ "pygit2>=1.6; python_version>='3.11'",
38
39
  "pyyaml>=5.4",
39
40
  "requests (>=2, <3)",
40
41
  "rich>=11.2.0",
@@ -11,6 +11,7 @@ from ruyi.utils.global_mode import (
11
11
  TRUTHY_ENV_VAR_VALUES,
12
12
  is_env_var_truthy,
13
13
  )
14
+ from ruyi.utils.node_info import probe_for_container_runtime
14
15
 
15
16
  # NOTE: no imports that directly or indirectly pull in pygit2 should go here,
16
17
  # because import of pygit2 will fail if done before ssl_patch. Notably this
@@ -32,6 +33,9 @@ def _is_allowed_to_run_as_root() -> bool:
32
33
  # CI environments are usually considered to be controlled, and safe
33
34
  # for root usage.
34
35
  return True
36
+ if probe_for_container_runtime(os.environ) != "unknown":
37
+ # So are container environments.
38
+ return True
35
39
  return False
36
40
 
37
41
 
@@ -6,6 +6,7 @@ from typing import Final, TYPE_CHECKING
6
6
  from ..config import GlobalConfig
7
7
  from ..telemetry.scope import TelemetryScope
8
8
  from ..utils.global_mode import GlobalModeProvider
9
+ from ..version import RUYI_SEMVER
9
10
  from . import RUYI_ENTRYPOINT_NAME
10
11
  from .oobe import OOBE
11
12
 
@@ -22,7 +23,11 @@ def is_called_as_ruyi(argv0: str) -> bool:
22
23
 
23
24
 
24
25
  def should_prompt_for_renaming(argv0: str) -> bool:
25
- return os.path.basename(argv0).lower().startswith(f"{RUYI_ENTRYPOINT_NAME}-")
26
+ # We need to allow things like "ruyi-qemu" through, to not break our mux.
27
+ # Only consider filenames starting with both our name *and* version to be
28
+ # un-renamed onefile artifacts that warrant a rename prompt.
29
+ likely_artifact_name_prefix = f"{RUYI_ENTRYPOINT_NAME}-{RUYI_SEMVER}."
30
+ return os.path.basename(argv0).lower().startswith(likely_artifact_name_prefix)
26
31
 
27
32
 
28
33
  def main(gm: GlobalModeProvider, gc: GlobalConfig, argv: list[str]) -> int:
@@ -65,7 +65,7 @@ class OOBE:
65
65
  handler()
66
66
 
67
67
  def _builtin_shell_completion_tip(self) -> None:
68
- from ..telemetry.node_info import probe_for_shell
68
+ from ..utils.node_info import probe_for_shell
69
69
  from .completion import SUPPORTED_SHELLS
70
70
 
71
71
  # Only show the tip if we're not externally managed by a package manager,
@@ -9,14 +9,46 @@ from typing import Any, Final, Iterator, TypedDict
9
9
  from ...config import GlobalConfig
10
10
  from ...log import RuyiLogger, humanize_list
11
11
  from ...ruyipkg.atom import Atom
12
- from ...ruyipkg.pkg_manifest import EmulatorProgDecl
12
+ from ...ruyipkg.pkg_manifest import BoundPackageManifest, EmulatorProgDecl
13
13
  from ...ruyipkg.profile import ProfileProxy
14
14
  from ...utils.global_mode import ProvidesGlobalMode
15
15
  from ...utils.templating import render_template_str
16
- from . import ConfiguredTargetTuple
17
16
  from .emulator_cfg import ResolvedEmulatorProg
18
17
 
19
18
 
19
+ class ConfiguredTargetTuple(TypedDict):
20
+ target: str
21
+ toolchain_root: PathLike[Any]
22
+ toolchain_sysroot: PathLike[Any] | None
23
+ toolchain_flags: str
24
+ binutils_flavor: str
25
+ cc_flavor: str
26
+ gcc_install_dir: PathLike[Any] | None
27
+
28
+
29
+ class VenvPackageInfo(TypedDict):
30
+ repo_id: str
31
+ category: str
32
+ name: str
33
+ version: str
34
+
35
+
36
+ class VenvMetadata(TypedDict):
37
+ emulator_pkgs: dict[str, VenvPackageInfo]
38
+ extra_pkgs: list[VenvPackageInfo]
39
+ sysroot_pkg: VenvPackageInfo | None
40
+ toolchain_pkgs: dict[str, VenvPackageInfo]
41
+
42
+
43
+ def _venv_pkg_info_from_pkg(pkg: BoundPackageManifest) -> VenvPackageInfo:
44
+ return VenvPackageInfo(
45
+ repo_id=pkg.repo_id,
46
+ category=pkg.category,
47
+ name=pkg.name,
48
+ version=pkg.ver,
49
+ )
50
+
51
+
20
52
  def do_make_venv(
21
53
  config: GlobalConfig,
22
54
  host: str,
@@ -50,6 +82,12 @@ def do_make_venv(
50
82
  seen_target_tuples: set[str] = set()
51
83
  targets: list[ConfiguredTargetTuple] = []
52
84
  warn_differing_target_arch = False
85
+ venv_metadata = VenvMetadata(
86
+ emulator_pkgs={},
87
+ extra_pkgs=[],
88
+ sysroot_pkg=None,
89
+ toolchain_pkgs={},
90
+ )
53
91
 
54
92
  for tc_atom_str in tc_atoms_str:
55
93
  tc_atom = Atom.parse(tc_atom_str)
@@ -97,6 +135,7 @@ def do_make_venv(
97
135
  if with_sysroot:
98
136
  if tc_sysroot_relpath := tc_pm.toolchain_metadata.included_sysroot:
99
137
  tc_sysroot_dir = pathlib.Path(toolchain_root) / tc_sysroot_relpath
138
+ venv_metadata["sysroot_pkg"] = _venv_pkg_info_from_pkg(tc_pm)
100
139
  else:
101
140
  if sysroot_atom_str is None:
102
141
  logger.F(
@@ -156,6 +195,8 @@ def do_make_venv(
156
195
  )
157
196
  return 1
158
197
 
198
+ venv_metadata["sysroot_pkg"] = _venv_pkg_info_from_pkg(gcc_pkg_pm)
199
+
159
200
  # derive flags for (the quirks of) this toolchain
160
201
  tc_flags = profile.get_common_flags(tc_pm.toolchain_metadata.quirks)
161
202
 
@@ -177,6 +218,7 @@ def do_make_venv(
177
218
  logger.D(f"configuration for {target_tuple}: {configured_target}")
178
219
  targets.append(configured_target)
179
220
  seen_target_tuples.add(target_tuple)
221
+ venv_metadata["toolchain_pkgs"][target_tuple] = _venv_pkg_info_from_pkg(tc_pm)
180
222
 
181
223
  # record the target architecture for use in emulator package matching
182
224
  if not target_arch:
@@ -236,6 +278,8 @@ def do_make_venv(
236
278
  logger.F("cannot find the installed directory for the emulator")
237
279
  return 1
238
280
 
281
+ venv_metadata["emulator_pkgs"][target_arch] = _venv_pkg_info_from_pkg(emu_pm)
282
+
239
283
  # Now resolve extra commands to provide in the venv.
240
284
  extra_cmds: dict[str, str] = {}
241
285
  if extra_cmd_atoms_str:
@@ -276,6 +320,8 @@ def do_make_venv(
276
320
  return 1
277
321
  cmd_root = pathlib.Path(cmd_root)
278
322
 
323
+ venv_metadata["extra_pkgs"].append(_venv_pkg_info_from_pkg(extra_cmd_pm))
324
+
279
325
  for cmd, cmd_rel_path in extra_cmds_decl.items():
280
326
  # resolve the command path
281
327
  cmd_path = (cmd_root / cmd_rel_path).resolve()
@@ -305,6 +351,7 @@ def do_make_venv(
305
351
  emu_progs,
306
352
  emu_root,
307
353
  extra_cmds,
354
+ venv_metadata,
308
355
  override_name,
309
356
  )
310
357
  maker.provision()
@@ -350,6 +397,7 @@ class VenvMaker:
350
397
  emulator_progs: list[EmulatorProgDecl] | None,
351
398
  emulator_root: PathLike[Any] | None,
352
399
  extra_cmds: dict[str, str] | None,
400
+ metadata: VenvMetadata,
353
401
  override_name: str | None = None,
354
402
  ) -> None:
355
403
  self.gc = gc
@@ -359,6 +407,7 @@ class VenvMaker:
359
407
  self.emulator_progs = emulator_progs
360
408
  self.emulator_root = emulator_root
361
409
  self.extra_cmds = extra_cmds or {}
410
+ self.metadata = metadata
362
411
  self.override_name = override_name
363
412
 
364
413
  self.bindir = self.venv_root / "bin"
@@ -415,6 +464,7 @@ class VenvMaker:
415
464
  env_data = {
416
465
  "profile": self.profile.id,
417
466
  "sysroot": self.sysroot_destdir(None),
467
+ "metadata": self.metadata,
418
468
  }
419
469
  self.render_and_write(
420
470
  venv_root / "ruyi-venv.toml",
@@ -44,7 +44,7 @@ class RuyiHostAPI:
44
44
 
45
45
  @property
46
46
  def ruyi_version(self) -> str:
47
- return str(RUYI_SEMVER)
47
+ return RUYI_SEMVER
48
48
 
49
49
  @property
50
50
  def ruyi_plugin_api_rev(self) -> int:
@@ -148,7 +148,7 @@ class UnsandboxedRuyiPluginLoader(BasePluginLoader[UnsandboxedModuleDict]):
148
148
  @staticmethod
149
149
  def source_to_code(
150
150
  data: "Buffer | str | ast.Module",
151
- path: "Buffer | str | os.PathLike[str]" = "<string>",
151
+ path: "str | os.PathLike[str]" = "<string>",
152
152
  ) -> CodeType:
153
153
  mod_ast: ast.Module
154
154
  if isinstance(data, ast.Module):
@@ -11,7 +11,7 @@ RESOURCES: Final = {
11
11
  "prompt.venv-created.txt.jinja": b"eNp1kTFvwkAMhff7FV7YStjbqWLqwMZSISSOO4dYJOfIvoRGiP9eXwR0KTedbOv5e8/bBmEkyYNvAZP9OHWYMpBC4gsEQZ8xVs598wCdn8CHTKPVgDIcJ1AeJFA6QTYh3/fCvVBp3+eIE2gQ6k0ylSG3Owli2h8p7VZ7iCQYMsv0Bj5FiPjUN3FKI5+L+EGGiZZ/zUPlroslUA06qTBnWNyc+4RaUJtHbdUL1vRTrPhWGYxtJDUgjHeW/5xX7mt270dPrT+25iTPszW3LV8KTe9z8+4c2LubuV6fILeb2ZrpMEUDLGDbFyHPWIE7VLhQbsDCjtOy8xFhvfFnhMzchsYbbU0tupLQBtUiDcKqc7GCdYPh/MoOzFA1iw2w4oezdaWujwiKhhpEymXNoP5kp02aZQjleFq5Xz21xdY=", # fmt: skip
12
12
  "ruyi-activate.bash.jinja": b"eNp9lN1u2kAQhe/3KSYGqiSVRUnuqIhEGqRESgLCBClKI2uxx/JKZh2t126o6yfqI/QuT9bxH2CHhBvEzpn1d2YO7sDCFxF4IkBYx5GGFUIcoQu/hPbBiMJYOQgrIfsq3giTO1okXKMBp54K17DikX/KOrAJY3C4lKEGFUsQGlyh0NHBhjEmPHgCo5tejq1r25o+zH9MzMyAEZ19M+D5O2gfJQP6oOOHYDzSZQVL9XSdE0aOEi96CD+79XHefPHlrGx8pUeenzNPMFaAulijwvEJpIWoAwoj1BAGLqBMhArlGqWGhCvBVwFGleqIcM3f0E2X4/lXO4Nn6tOxkhFoFSOQHSoAMbnoBFzRsLgGHgRFO1WrfnJszx8eb+zp7ZU9Gy+uh3QZ+YU9w/knL42MblNrbMv4+hIqXai2Z7HMfTQ7imLuvzQhZMID4eYDoKcV7bQhx8ei7tPewFRwdtF3MenLmOg/xbcGH8Bbgya7NXiPbg0+Jq9qNXhZL8rLyf3y0Jk9m0/vZosa94mAiXVQRUqG0sWIFpWvH1vEHbAw8KAWHLWwTA9a4anZMkYhL0VCKQww4Y3gtDPXpGBsCz9K050T+AO0hixj1aB2tllztzTiMhTVj62wT//MYVXbDwr7LAAHl5/28mHuhnw/vpuA2ctYe+4NB6WstpH2TMAgwsN9RveYXhco+Rphz4JxYpSN0iWA3vth1Psu3yNlMnfFqxtrfHk7qURmO6ONpBFCSl8kYtvsvv2d0+5g/8ryquztHzTke2mmRPwHax2J0Q==", # fmt: skip
13
13
  "ruyi-cache.toml.jinja": b"eNptUs1uhCAYvPsUX2nMtknjoccmve0e9tK9eDOGsIJK1r8CmhjjuxcUF6uexG+GmWHgFX5u4eULwpxLSHnBQH9LUpGMUbj3INqeB3C+GRpcztfwxfOihCQ5o7j7jL3BB57CLytbfOcV+ONz+Q1oGBwyjkhzWUU13R/tvkbUxhMbEqs6AzjxYINOZmkt4PEBHWjJDR5wxUr59q5VtPFDO9oMnTH3ZnezX+P/k6xFFREZU3Iltkq0gFY/9lRdF0lOeGXOSLlYHKPTFjnFUwo3TguSySP+BFj6XFMXIQfLXoq6VijW0XbTIz0LzYr7O9DiWZJgXklFigLrqJP0ZuaEN8Ch7LPobbtJSXHJFKFEEVyS5rjmHQvZwlHsUSZXpzR/S7PT3WDVNvoRuxpWU9epy/cHatoHPQ==", # fmt: skip
14
- "ruyi-venv.toml.jinja": b"eNqLTs7PS8tMj+UqKMpPy8xJVbBVUKquVoDxamuVuKpVFTLTFIori4vy80sUdFVruWBsiFoYD6JWVyE1LwWoHqgMAMZMHuE=", # fmt: skip
14
+ "ruyi-venv.toml.jinja": b"eNqtkOFqwyAQx7/7FBIIbWEN7AH2JEHCYUwqbTxRN1ZC3n0atQlpSxnbN/V+3v3uX3NUnewZ0QY7eRH0gxbjSPNtmgoyllR21F6tQXT0WE4knyObb5E9UqFaz3uM1INw0IIDRr6EsRKV//JOQscBuEGqz32Tmb0+zM2N0NjINovUu/SwY/MEDk70aK5LPb8kQMEglmK4pcKikGrpIZWTehQL9nHvrFcXac/GSxcsELf1Kg38DL2wVWIYCRPWyz1pc/Cjw6Als+1UMXxewKEJvI1zPdKhoQ5ML1wDhp/eqKZSPf9VSScGu48BP9DOeBWSWfUNwdzvolfWQaR8tcK3M3Dvv1VeU7PnI9EAsb8rOcQLP4FUv4t1++1Vrjf+X4L9AYyLQa0=", # fmt: skip
15
15
  "toolchain.cmake.jinja": b"eNqFkVFrwjAUhd/7Ky6IMGF274M9dG2cZWlT0joUhJDVaIuajKQTR+l/X6zOWccwb+F+5+Scmx5MjIBNuRaPTs/pQb7lawGu68Lc3g5nGPiR94pYRgj2x14Ys1GI0VNdw07IHdNKVdA0D5VSm7zgpXSPFnOn7g+hXIL5Mi3Tb64MwzjNPIxZQtEonB4Mf9CmOcmFXFiHs9LGchwjqrujQTpLMxSx2IsQ4FJ+7gd/hwklPkpTQsH6f2iVC2OUti9csj7zSZTYVi2V59fj6bQL7PctUfcv+w1tzF/NKIwDRgnJWOJlY+iUa5UX1YzgOi9gaXMVgi+ENsDlwn7Ku+a6FAZKCVUhoOJ6JSqr3JVaya2Q1X1XbfutNN+eBYUyHfzffCwiATrs6oV6EcToDdHBDRiHz9SjMyAxnt1iw9jHkwCd2G+4PsQk", # fmt: skip
16
16
  }
17
17
 
@@ -3,8 +3,8 @@ from typing import Iterable, TypeAlias, TypedDict, TYPE_CHECKING
3
3
  if TYPE_CHECKING:
4
4
  from typing_extensions import NotRequired
5
5
 
6
+ from ..utils.node_info import NodeInfo
6
7
  from .event import TelemetryEvent
7
- from .node_info import NodeInfo
8
8
 
9
9
 
10
10
  class AggregatedTelemetryEvent(TypedDict):
@@ -8,7 +8,7 @@ from typing import Callable, TYPE_CHECKING, cast
8
8
  import uuid
9
9
 
10
10
  from ..log import RuyiLogger
11
- from .node_info import NodeInfo, gather_node_info
11
+ from ..utils.node_info import NodeInfo, gather_node_info
12
12
  from .scope import TelemetryScope
13
13
  from .store import TelemetryStore
14
14
 
@@ -8,10 +8,10 @@ from typing import Callable, Final, Iterable
8
8
  import uuid
9
9
 
10
10
  from ..log import RuyiLogger
11
+ from ..utils.node_info import NodeInfo
11
12
  from ..utils.url import urljoin_for_sure
12
13
  from .aggregate import UploadPayload, aggregate_events
13
14
  from .event import TelemetryEvent, is_telemetry_event
14
- from .node_info import NodeInfo
15
15
  from .scope import TelemetryScope
16
16
 
17
17
  # e.g. "run.202410201845.d06ca5d668e64fec833ed3e6eb926a2c.ndjson"
@@ -165,7 +165,7 @@ class TelemetryStore:
165
165
  payload: UploadPayload = {
166
166
  "fmt": 1,
167
167
  "nonce": payload_nonce,
168
- "ruyi_version": str(RUYI_SEMVER),
168
+ "ruyi_version": RUYI_SEMVER,
169
169
  "events": aggregate_data,
170
170
  }
171
171
  if installation_data is not None:
File without changes
@@ -143,7 +143,7 @@ def _probe_cli_autocomplete(env: Mapping[str, str], argv: list[str]) -> bool:
143
143
  if arg.startswith("--output-completion-script"):
144
144
  return True
145
145
 
146
- return "_ARGCOMPLETE" in os.environ
146
+ return "_ARGCOMPLETE" in env
147
147
 
148
148
 
149
149
  class EnvGlobalModeProvider(GlobalModeProvider):
@@ -1,5 +1,6 @@
1
1
  import glob
2
2
  import os
3
+ import pathlib
3
4
  import platform
4
5
  import re
5
6
  import subprocess
@@ -10,7 +11,7 @@ import uuid
10
11
  if TYPE_CHECKING:
11
12
  from typing_extensions import NotRequired
12
13
 
13
- from ..utils.ci import probe_for_ci
14
+ from .ci import probe_for_ci
14
15
 
15
16
 
16
17
  class NodeInfo(TypedDict):
@@ -161,6 +162,56 @@ def probe_for_shell(os_environ: Mapping[str, str]) -> str:
161
162
  return "unknown"
162
163
 
163
164
 
165
+ def probe_for_container_runtime(os_environ: Mapping[str, str]) -> str:
166
+ """Check if we are likely running in a container. Probes FS and environment
167
+ for signatures of known container runtimes."""
168
+
169
+ # check environment markers first
170
+
171
+ if "KUBERNETES_SERVICE_HOST" in os_environ:
172
+ return "kubernetes"
173
+
174
+ if "container" in os_environ:
175
+ v = os_environ["container"].lower()
176
+ if v == "oci":
177
+ return "other-oci-compliant"
178
+ # could be e.g. "lxc", "lxc-libvirt", "systemd-nspawn", etc.
179
+ return v
180
+
181
+ # check for filesystem markers
182
+
183
+ if os.path.exists("/run/.containerenv"):
184
+ return "podman"
185
+ # Docker must be checked after Podman
186
+ if os.path.exists("/.dockerenv"):
187
+ return "docker"
188
+
189
+ try:
190
+ v = pathlib.Path("/run/systemd/container").read_text(encoding="utf-8").strip()
191
+ if v:
192
+ return v.lower()
193
+ except Exception:
194
+ pass
195
+
196
+ if _probe_for_wsl():
197
+ return "wsl"
198
+
199
+ return "unknown"
200
+
201
+
202
+ def _probe_for_wsl() -> bool:
203
+ if sys.platform != "linux":
204
+ return False
205
+ # http://github.com/Microsoft/WSL/issues/423#issuecomment-221627364
206
+ for path in ("/proc/sys/kernel/osrelease", "/proc/version"):
207
+ try:
208
+ ver = pathlib.Path(path).read_text(encoding="utf-8")
209
+ except Exception:
210
+ continue
211
+ return "Microsoft" in ver or "WSL" in ver
212
+ return False
213
+
214
+
164
215
  def gather_node_info(report_uuid: uuid.UUID | None = None) -> NodeInfo:
165
216
  arch = platform.machine()
166
217
  libc = probe_for_libc()
@@ -0,0 +1,20 @@
1
+ from typing import Final
2
+
3
+ RUYI_SEMVER: Final = "0.43.0"
4
+ RUYI_USER_AGENT: Final = f"ruyi/{RUYI_SEMVER}"
5
+
6
+ COPYRIGHT_NOTICE: Final = """\
7
+ Copyright (C) Institute of Software, Chinese Academy of Sciences (ISCAS).
8
+ All rights reserved.
9
+ License: Apache-2.0 <https://www.apache.org/licenses/LICENSE-2.0>
10
+ \
11
+ """
12
+
13
+ MPL_REDIST_NOTICE: Final = """\
14
+ This distribution of ruyi contains code licensed under the Mozilla Public
15
+ License 2.0 (https://mozilla.org/MPL/2.0/). You can get the respective
16
+ project's sources from the project's official website:
17
+
18
+ * certifi: https://github.com/certifi/python-certifi
19
+ \
20
+ """
@@ -1,12 +0,0 @@
1
- from os import PathLike
2
- from typing import Any, TypedDict
3
-
4
-
5
- class ConfiguredTargetTuple(TypedDict):
6
- target: str
7
- toolchain_root: PathLike[Any]
8
- toolchain_sysroot: PathLike[Any] | None
9
- toolchain_flags: str
10
- binutils_flavor: str
11
- cc_flavor: str
12
- gcc_install_dir: PathLike[Any] | None
@@ -1,67 +0,0 @@
1
- import importlib.metadata
2
- from typing import Final, TYPE_CHECKING
3
-
4
- import packaging.version
5
-
6
- if TYPE_CHECKING:
7
- # pyright only works with semver 3.x
8
- from semver.version import Version
9
- else:
10
- try:
11
- from semver.version import Version # type: ignore[import-untyped,unused-ignore]
12
- except ModuleNotFoundError:
13
- # semver 2.x
14
- from semver import VersionInfo as Version # type: ignore[import-untyped,unused-ignore]
15
-
16
- # NOTE: one cannot print logs in the version helpers, because the version info
17
- # is initialized so early (before argparse can look at argv because --version
18
- # requires version info to be ready) that the porcelain status is not yet
19
- # available.
20
-
21
- _PYPI_PRERELEASE_KINDS_MAP: Final = {
22
- "a": "alpha",
23
- "b": "beta",
24
- "rc": "rc",
25
- }
26
-
27
-
28
- # based on https://python-semver.readthedocs.io/en/3.0.2/advanced/convert-pypi-to-semver.html
29
- def _convert2semver(ver: packaging.version.Version) -> Version:
30
- if ver.epoch:
31
- raise ValueError("Can't convert an epoch to semver")
32
- if ver.post:
33
- raise ValueError("Can't convert a post part to semver")
34
-
35
- pre: str | None = None
36
- if ver.pre:
37
- kind, val = ver.pre
38
- pre = f"{_PYPI_PRERELEASE_KINDS_MAP.get(kind, kind)}.{val}"
39
-
40
- maj, min, pat = ver.release[:3]
41
- return Version(maj, min, pat, prerelease=pre, build=ver.dev)
42
-
43
-
44
- def _init_pkg_semver() -> Version:
45
- pkg_pypi_ver = packaging.version.Version(importlib.metadata.version("ruyi"))
46
- # log.D(f"PyPI-style version of ruyi: {pkg_pypi_ver}")
47
- return _convert2semver(pkg_pypi_ver)
48
-
49
-
50
- RUYI_SEMVER: Final = _init_pkg_semver()
51
- RUYI_USER_AGENT: Final = f"ruyi/{RUYI_SEMVER}"
52
-
53
- COPYRIGHT_NOTICE: Final = """\
54
- Copyright (C) Institute of Software, Chinese Academy of Sciences (ISCAS).
55
- All rights reserved.
56
- License: Apache-2.0 <https://www.apache.org/licenses/LICENSE-2.0>
57
- \
58
- """
59
-
60
- MPL_REDIST_NOTICE: Final = """\
61
- This distribution of ruyi contains code licensed under the Mozilla Public
62
- License 2.0 (https://mozilla.org/MPL/2.0/). You can get the respective
63
- project's sources from the project's official website:
64
-
65
- * certifi: https://github.com/certifi/python-certifi
66
- \
67
- """
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes