ruyi 0.39.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.
Files changed (101) hide show
  1. ruyi/__init__.py +21 -0
  2. ruyi/__main__.py +98 -0
  3. ruyi/cli/__init__.py +5 -0
  4. ruyi/cli/builtin_commands.py +14 -0
  5. ruyi/cli/cmd.py +224 -0
  6. ruyi/cli/completer.py +50 -0
  7. ruyi/cli/completion.py +26 -0
  8. ruyi/cli/config_cli.py +153 -0
  9. ruyi/cli/main.py +111 -0
  10. ruyi/cli/self_cli.py +295 -0
  11. ruyi/cli/user_input.py +127 -0
  12. ruyi/cli/version_cli.py +45 -0
  13. ruyi/config/__init__.py +401 -0
  14. ruyi/config/editor.py +92 -0
  15. ruyi/config/errors.py +76 -0
  16. ruyi/config/news.py +39 -0
  17. ruyi/config/schema.py +197 -0
  18. ruyi/device/__init__.py +0 -0
  19. ruyi/device/provision.py +591 -0
  20. ruyi/device/provision_cli.py +40 -0
  21. ruyi/log/__init__.py +272 -0
  22. ruyi/mux/.gitignore +1 -0
  23. ruyi/mux/__init__.py +0 -0
  24. ruyi/mux/runtime.py +213 -0
  25. ruyi/mux/venv/__init__.py +12 -0
  26. ruyi/mux/venv/emulator_cfg.py +41 -0
  27. ruyi/mux/venv/maker.py +782 -0
  28. ruyi/mux/venv/venv_cli.py +92 -0
  29. ruyi/mux/venv_cfg.py +214 -0
  30. ruyi/pluginhost/__init__.py +0 -0
  31. ruyi/pluginhost/api.py +206 -0
  32. ruyi/pluginhost/ctx.py +222 -0
  33. ruyi/pluginhost/paths.py +135 -0
  34. ruyi/pluginhost/plugin_cli.py +37 -0
  35. ruyi/pluginhost/unsandboxed.py +246 -0
  36. ruyi/py.typed +0 -0
  37. ruyi/resource_bundle/__init__.py +20 -0
  38. ruyi/resource_bundle/__main__.py +55 -0
  39. ruyi/resource_bundle/data.py +26 -0
  40. ruyi/ruyipkg/__init__.py +0 -0
  41. ruyi/ruyipkg/admin_checksum.py +88 -0
  42. ruyi/ruyipkg/admin_cli.py +83 -0
  43. ruyi/ruyipkg/atom.py +184 -0
  44. ruyi/ruyipkg/augmented_pkg.py +212 -0
  45. ruyi/ruyipkg/canonical_dump.py +320 -0
  46. ruyi/ruyipkg/checksum.py +39 -0
  47. ruyi/ruyipkg/cli_completion.py +42 -0
  48. ruyi/ruyipkg/distfile.py +208 -0
  49. ruyi/ruyipkg/entity.py +387 -0
  50. ruyi/ruyipkg/entity_cli.py +123 -0
  51. ruyi/ruyipkg/entity_provider.py +273 -0
  52. ruyi/ruyipkg/fetch.py +271 -0
  53. ruyi/ruyipkg/host.py +55 -0
  54. ruyi/ruyipkg/install.py +554 -0
  55. ruyi/ruyipkg/install_cli.py +150 -0
  56. ruyi/ruyipkg/list.py +126 -0
  57. ruyi/ruyipkg/list_cli.py +79 -0
  58. ruyi/ruyipkg/list_filter.py +173 -0
  59. ruyi/ruyipkg/msg.py +99 -0
  60. ruyi/ruyipkg/news.py +123 -0
  61. ruyi/ruyipkg/news_cli.py +78 -0
  62. ruyi/ruyipkg/news_store.py +183 -0
  63. ruyi/ruyipkg/pkg_manifest.py +657 -0
  64. ruyi/ruyipkg/profile.py +208 -0
  65. ruyi/ruyipkg/profile_cli.py +33 -0
  66. ruyi/ruyipkg/protocols.py +55 -0
  67. ruyi/ruyipkg/repo.py +763 -0
  68. ruyi/ruyipkg/state.py +345 -0
  69. ruyi/ruyipkg/unpack.py +369 -0
  70. ruyi/ruyipkg/unpack_method.py +91 -0
  71. ruyi/ruyipkg/update_cli.py +54 -0
  72. ruyi/telemetry/__init__.py +0 -0
  73. ruyi/telemetry/aggregate.py +72 -0
  74. ruyi/telemetry/event.py +41 -0
  75. ruyi/telemetry/node_info.py +192 -0
  76. ruyi/telemetry/provider.py +411 -0
  77. ruyi/telemetry/scope.py +43 -0
  78. ruyi/telemetry/store.py +238 -0
  79. ruyi/telemetry/telemetry_cli.py +127 -0
  80. ruyi/utils/__init__.py +0 -0
  81. ruyi/utils/ar.py +74 -0
  82. ruyi/utils/ci.py +63 -0
  83. ruyi/utils/frontmatter.py +38 -0
  84. ruyi/utils/git.py +169 -0
  85. ruyi/utils/global_mode.py +204 -0
  86. ruyi/utils/l10n.py +83 -0
  87. ruyi/utils/markdown.py +73 -0
  88. ruyi/utils/nuitka.py +33 -0
  89. ruyi/utils/porcelain.py +51 -0
  90. ruyi/utils/prereqs.py +77 -0
  91. ruyi/utils/ssl_patch.py +170 -0
  92. ruyi/utils/templating.py +34 -0
  93. ruyi/utils/toml.py +115 -0
  94. ruyi/utils/url.py +7 -0
  95. ruyi/utils/xdg_basedir.py +80 -0
  96. ruyi/version.py +67 -0
  97. ruyi-0.39.0.dist-info/LICENSE-Apache.txt +201 -0
  98. ruyi-0.39.0.dist-info/METADATA +403 -0
  99. ruyi-0.39.0.dist-info/RECORD +101 -0
  100. ruyi-0.39.0.dist-info/WHEEL +4 -0
  101. ruyi-0.39.0.dist-info/entry_points.txt +3 -0
ruyi/config/schema.py ADDED
@@ -0,0 +1,197 @@
1
+ import datetime
2
+ import sys
3
+ from typing import Final, Sequence
4
+
5
+ from .errors import (
6
+ InvalidConfigKeyError,
7
+ InvalidConfigSectionError,
8
+ InvalidConfigValueError,
9
+ InvalidConfigValueTypeError,
10
+ )
11
+
12
+
13
+ def parse_config_key(key: str | Sequence[str]) -> list[str]:
14
+ if isinstance(key, str):
15
+ return key.split(".")
16
+ return list(key)
17
+
18
+
19
+ SECTION_INSTALLATION: Final = "installation"
20
+ KEY_INSTALLATION_EXTERNALLY_MANAGED: Final = "externally_managed"
21
+
22
+ SECTION_PACKAGES: Final = "packages"
23
+ KEY_PACKAGES_PRERELEASES: Final = "prereleases"
24
+
25
+ SECTION_REPO: Final = "repo"
26
+ KEY_REPO_BRANCH: Final = "branch"
27
+ KEY_REPO_LOCAL: Final = "local"
28
+ KEY_REPO_REMOTE: Final = "remote"
29
+
30
+ SECTION_TELEMETRY: Final = "telemetry"
31
+ KEY_TELEMETRY_MODE: Final = "mode"
32
+ KEY_TELEMETRY_PM_TELEMETRY_URL: Final = "pm_telemetry_url"
33
+ KEY_TELEMETRY_UPLOAD_CONSENT: Final = "upload_consent"
34
+
35
+
36
+ def validate_section(section: str) -> None:
37
+ if section not in (
38
+ SECTION_INSTALLATION,
39
+ SECTION_PACKAGES,
40
+ SECTION_REPO,
41
+ SECTION_TELEMETRY,
42
+ ):
43
+ raise InvalidConfigSectionError(section)
44
+
45
+
46
+ def get_expected_type_for_config_key(key: str | Sequence[str]) -> type:
47
+ parsed_key = parse_config_key(key)
48
+ if len(parsed_key) != 2:
49
+ # for now there's no nested config option
50
+ raise InvalidConfigKeyError(key)
51
+
52
+ section, sel = parsed_key
53
+ if section == SECTION_INSTALLATION:
54
+ return _get_expected_type_for_section_installation(sel)
55
+ elif section == SECTION_PACKAGES:
56
+ return _get_expected_type_for_section_packages(sel)
57
+ elif section == SECTION_REPO:
58
+ return _get_expected_type_for_section_repo(sel)
59
+ elif section == SECTION_TELEMETRY:
60
+ return _get_expected_type_for_section_telemetry(sel)
61
+ else:
62
+ raise InvalidConfigKeyError(key)
63
+
64
+
65
+ def _get_expected_type_for_section_installation(sel: str) -> type:
66
+ if sel == KEY_INSTALLATION_EXTERNALLY_MANAGED:
67
+ return bool
68
+ else:
69
+ raise InvalidConfigKeyError(sel)
70
+
71
+
72
+ def _get_expected_type_for_section_packages(sel: str) -> type:
73
+ if sel == KEY_PACKAGES_PRERELEASES:
74
+ return bool
75
+ else:
76
+ raise InvalidConfigKeyError(sel)
77
+
78
+
79
+ def _get_expected_type_for_section_repo(sel: str) -> type:
80
+ if sel == KEY_REPO_BRANCH:
81
+ return str
82
+ elif sel == KEY_REPO_LOCAL:
83
+ return str
84
+ elif sel == KEY_REPO_REMOTE:
85
+ return str
86
+ else:
87
+ raise InvalidConfigKeyError(sel)
88
+
89
+
90
+ def _get_expected_type_for_section_telemetry(sel: str) -> type:
91
+ if sel == KEY_TELEMETRY_MODE:
92
+ return str
93
+ elif sel == KEY_TELEMETRY_PM_TELEMETRY_URL:
94
+ return str
95
+ elif sel == KEY_TELEMETRY_UPLOAD_CONSENT:
96
+ return datetime.datetime
97
+ else:
98
+ raise InvalidConfigKeyError(sel)
99
+
100
+
101
+ def ensure_valid_config_kv(
102
+ key: str | Sequence[str],
103
+ check_val: bool = False,
104
+ val: object | None = None,
105
+ ) -> None:
106
+ parsed_key = parse_config_key(key)
107
+ if len(parsed_key) != 2:
108
+ # for now there's no nested config option
109
+ raise InvalidConfigKeyError(key)
110
+
111
+ expected_type = get_expected_type_for_config_key(parsed_key)
112
+ # validity of config key is already checked by get_expected_type_for_config_key
113
+ _ensure_value_type(key, check_val, val, expected_type)
114
+
115
+ if not check_val:
116
+ return
117
+
118
+ section, sel = parsed_key
119
+ if section == SECTION_TELEMETRY:
120
+ return _extra_validate_section_telemetry_kv(key, sel, val)
121
+
122
+
123
+ def _ensure_value_type(
124
+ key: str | Sequence[str],
125
+ check_val: bool,
126
+ val: object | None,
127
+ expected: type,
128
+ ) -> None:
129
+ if check_val and not isinstance(val, expected):
130
+ raise InvalidConfigValueTypeError(key, val, expected)
131
+
132
+
133
+ def _extra_validate_section_telemetry_kv(
134
+ key: str | Sequence[str],
135
+ sel: str,
136
+ val: object | None,
137
+ ) -> None:
138
+ if sel == KEY_TELEMETRY_MODE:
139
+ # value type is already ensured earlier
140
+ if val not in ("local", "off", "on"):
141
+ raise InvalidConfigValueError(key, val)
142
+
143
+
144
+ def encode_value(v: object) -> str:
145
+ """Encodes the given config value into a string representation suitable for
146
+ display or storage into TOML config files."""
147
+
148
+ if isinstance(v, bool):
149
+ return "true" if v else "false"
150
+ elif isinstance(v, int):
151
+ return str(v)
152
+ elif isinstance(v, str):
153
+ return v
154
+ elif isinstance(v, datetime.datetime):
155
+ if v.tzinfo is None:
156
+ raise ValueError("only timezone-aware datetimes are supported for safety")
157
+ s = v.isoformat()
158
+ if s.endswith("+00:00"):
159
+ # use the shorter 'Z' suffix for UTC
160
+ return f"{s[:-6]}Z"
161
+ return s
162
+ else:
163
+ raise NotImplementedError(f"invalid type for config value: {type(v)}")
164
+
165
+
166
+ def decode_value(
167
+ key: str | Sequence[str] | type,
168
+ val: str,
169
+ ) -> object:
170
+ """Decodes the given string representation of a config value into a Python
171
+ value, directed by type information implied by the config key."""
172
+
173
+ if isinstance(key, type):
174
+ expected_type = key
175
+ else:
176
+ expected_type = get_expected_type_for_config_key(key)
177
+
178
+ if expected_type is bool:
179
+ if val in ("true", "yes", "1"):
180
+ return True
181
+ elif val in ("false", "no", "0"):
182
+ return False
183
+ else:
184
+ raise InvalidConfigValueError(key, val)
185
+ elif expected_type is int:
186
+ return int(val, 10)
187
+ elif expected_type is str:
188
+ return val
189
+ elif expected_type is datetime.datetime:
190
+ if sys.version_info < (3, 11) and val.endswith("Z"):
191
+ # datetime.fromisoformat() did not support the 'Z' suffix until
192
+ # Python 3.11
193
+ val = f"{val[:-1]}+00:00"
194
+ v = datetime.datetime.fromisoformat(val)
195
+ return v.astimezone() if v.tzinfo is None else v
196
+ else:
197
+ raise NotImplementedError(f"invalid type for config value: {expected_type}")
File without changes