zexus 1.6.8 → 1.7.2

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 (177) hide show
  1. package/README.md +12 -5
  2. package/package.json +1 -1
  3. package/src/__init__.py +7 -0
  4. package/src/zexus/__init__.py +1 -1
  5. package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
  6. package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
  7. package/src/zexus/__pycache__/debug_sanitizer.cpython-312.pyc +0 -0
  8. package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
  9. package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
  10. package/src/zexus/__pycache__/input_validation.cpython-312.pyc +0 -0
  11. package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
  12. package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
  13. package/src/zexus/__pycache__/module_manager.cpython-312.pyc +0 -0
  14. package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
  15. package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
  16. package/src/zexus/__pycache__/security_enforcement.cpython-312.pyc +0 -0
  17. package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
  18. package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
  19. package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
  20. package/src/zexus/access_control_system/__pycache__/__init__.cpython-312.pyc +0 -0
  21. package/src/zexus/access_control_system/__pycache__/access_control.cpython-312.pyc +0 -0
  22. package/src/zexus/advanced_types.py +17 -2
  23. package/src/zexus/blockchain/__init__.py +411 -0
  24. package/src/zexus/blockchain/accelerator.py +1160 -0
  25. package/src/zexus/blockchain/chain.py +660 -0
  26. package/src/zexus/blockchain/consensus.py +821 -0
  27. package/src/zexus/blockchain/contract_vm.py +1019 -0
  28. package/src/zexus/blockchain/crypto.py +79 -14
  29. package/src/zexus/blockchain/events.py +526 -0
  30. package/src/zexus/blockchain/loadtest.py +721 -0
  31. package/src/zexus/blockchain/monitoring.py +350 -0
  32. package/src/zexus/blockchain/mpt.py +716 -0
  33. package/src/zexus/blockchain/multichain.py +951 -0
  34. package/src/zexus/blockchain/multiprocess_executor.py +338 -0
  35. package/src/zexus/blockchain/network.py +886 -0
  36. package/src/zexus/blockchain/node.py +666 -0
  37. package/src/zexus/blockchain/rpc.py +1203 -0
  38. package/src/zexus/blockchain/rust_bridge.py +421 -0
  39. package/src/zexus/blockchain/storage.py +423 -0
  40. package/src/zexus/blockchain/tokens.py +750 -0
  41. package/src/zexus/blockchain/upgradeable.py +1004 -0
  42. package/src/zexus/blockchain/verification.py +1602 -0
  43. package/src/zexus/blockchain/wallet.py +621 -0
  44. package/src/zexus/capability_system.py +184 -9
  45. package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
  46. package/src/zexus/cli/main.py +383 -34
  47. package/src/zexus/cli/zpm.py +1 -1
  48. package/src/zexus/compiler/__pycache__/bytecode.cpython-312.pyc +0 -0
  49. package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
  50. package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
  51. package/src/zexus/compiler/__pycache__/semantic.cpython-312.pyc +0 -0
  52. package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
  53. package/src/zexus/compiler/bytecode.py +124 -7
  54. package/src/zexus/compiler/compat_runtime.py +6 -2
  55. package/src/zexus/compiler/lexer.py +16 -5
  56. package/src/zexus/compiler/parser.py +108 -7
  57. package/src/zexus/compiler/semantic.py +18 -19
  58. package/src/zexus/compiler/zexus_ast.py +26 -1
  59. package/src/zexus/concurrency_system.py +79 -0
  60. package/src/zexus/config.py +54 -0
  61. package/src/zexus/crypto_bridge.py +244 -8
  62. package/src/zexus/dap/__init__.py +10 -0
  63. package/src/zexus/dap/__main__.py +4 -0
  64. package/src/zexus/dap/dap_server.py +391 -0
  65. package/src/zexus/dap/debug_engine.py +298 -0
  66. package/src/zexus/environment.py +112 -9
  67. package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
  68. package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
  69. package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
  70. package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
  71. package/src/zexus/evaluator/__pycache__/resource_limiter.cpython-312.pyc +0 -0
  72. package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
  73. package/src/zexus/evaluator/__pycache__/unified_execution.cpython-312.pyc +0 -0
  74. package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
  75. package/src/zexus/evaluator/bytecode_compiler.py +457 -37
  76. package/src/zexus/evaluator/core.py +644 -50
  77. package/src/zexus/evaluator/expressions.py +358 -62
  78. package/src/zexus/evaluator/functions.py +458 -20
  79. package/src/zexus/evaluator/resource_limiter.py +4 -4
  80. package/src/zexus/evaluator/statements.py +774 -122
  81. package/src/zexus/evaluator/unified_execution.py +573 -72
  82. package/src/zexus/evaluator/utils.py +14 -2
  83. package/src/zexus/evaluator_original.py +1 -1
  84. package/src/zexus/event_loop.py +186 -0
  85. package/src/zexus/lexer.py +742 -458
  86. package/src/zexus/lsp/__init__.py +1 -1
  87. package/src/zexus/lsp/definition_provider.py +163 -9
  88. package/src/zexus/lsp/server.py +22 -8
  89. package/src/zexus/lsp/symbol_provider.py +182 -9
  90. package/src/zexus/module_cache.py +239 -9
  91. package/src/zexus/module_manager.py +129 -1
  92. package/src/zexus/object.py +76 -6
  93. package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
  94. package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
  95. package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
  96. package/src/zexus/parser/parser.py +1349 -408
  97. package/src/zexus/parser/strategy_context.py +755 -58
  98. package/src/zexus/parser/strategy_structural.py +121 -21
  99. package/src/zexus/persistence.py +15 -1
  100. package/src/zexus/renderer/__init__.py +61 -0
  101. package/src/zexus/renderer/__pycache__/__init__.cpython-312.pyc +0 -0
  102. package/src/zexus/renderer/__pycache__/backend.cpython-312.pyc +0 -0
  103. package/src/zexus/renderer/__pycache__/canvas.cpython-312.pyc +0 -0
  104. package/src/zexus/renderer/__pycache__/color_system.cpython-312.pyc +0 -0
  105. package/src/zexus/renderer/__pycache__/layout.cpython-312.pyc +0 -0
  106. package/src/zexus/renderer/__pycache__/main_renderer.cpython-312.pyc +0 -0
  107. package/src/zexus/renderer/__pycache__/painter.cpython-312.pyc +0 -0
  108. package/src/zexus/renderer/backend.py +261 -0
  109. package/src/zexus/renderer/canvas.py +78 -0
  110. package/src/zexus/renderer/color_system.py +201 -0
  111. package/src/zexus/renderer/graphics.py +31 -0
  112. package/src/zexus/renderer/layout.py +222 -0
  113. package/src/zexus/renderer/main_renderer.py +66 -0
  114. package/src/zexus/renderer/painter.py +30 -0
  115. package/src/zexus/renderer/tk_backend.py +208 -0
  116. package/src/zexus/renderer/web_backend.py +260 -0
  117. package/src/zexus/runtime/__init__.py +10 -2
  118. package/src/zexus/runtime/__pycache__/__init__.cpython-312.pyc +0 -0
  119. package/src/zexus/runtime/__pycache__/async_runtime.cpython-312.pyc +0 -0
  120. package/src/zexus/runtime/__pycache__/load_manager.cpython-312.pyc +0 -0
  121. package/src/zexus/runtime/file_flags.py +137 -0
  122. package/src/zexus/runtime/load_manager.py +368 -0
  123. package/src/zexus/safety/__pycache__/__init__.cpython-312.pyc +0 -0
  124. package/src/zexus/safety/__pycache__/memory_safety.cpython-312.pyc +0 -0
  125. package/src/zexus/security.py +424 -34
  126. package/src/zexus/stdlib/fs.py +23 -18
  127. package/src/zexus/stdlib/http.py +289 -186
  128. package/src/zexus/stdlib/sockets.py +207 -163
  129. package/src/zexus/stdlib/websockets.py +282 -0
  130. package/src/zexus/stdlib_integration.py +369 -2
  131. package/src/zexus/strategy_recovery.py +6 -3
  132. package/src/zexus/type_checker.py +423 -0
  133. package/src/zexus/virtual_filesystem.py +189 -2
  134. package/src/zexus/vm/__init__.py +113 -3
  135. package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
  136. package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
  137. package/src/zexus/vm/__pycache__/bytecode_converter.cpython-312.pyc +0 -0
  138. package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
  139. package/src/zexus/vm/__pycache__/compiler.cpython-312.pyc +0 -0
  140. package/src/zexus/vm/__pycache__/gas_metering.cpython-312.pyc +0 -0
  141. package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
  142. package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
  143. package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
  144. package/src/zexus/vm/async_optimizer.py +80 -6
  145. package/src/zexus/vm/binary_bytecode.py +659 -0
  146. package/src/zexus/vm/bytecode.py +59 -11
  147. package/src/zexus/vm/bytecode_converter.py +26 -12
  148. package/src/zexus/vm/cabi.c +1985 -0
  149. package/src/zexus/vm/cabi.cpython-312-x86_64-linux-gnu.so +0 -0
  150. package/src/zexus/vm/cabi.h +127 -0
  151. package/src/zexus/vm/cache.py +561 -17
  152. package/src/zexus/vm/compiler.py +818 -51
  153. package/src/zexus/vm/fastops.c +15743 -0
  154. package/src/zexus/vm/fastops.cpython-312-x86_64-linux-gnu.so +0 -0
  155. package/src/zexus/vm/fastops.pyx +288 -0
  156. package/src/zexus/vm/gas_metering.py +50 -9
  157. package/src/zexus/vm/jit.py +364 -20
  158. package/src/zexus/vm/native_jit_backend.py +1816 -0
  159. package/src/zexus/vm/native_runtime.cpp +1388 -0
  160. package/src/zexus/vm/native_runtime.cpython-312-x86_64-linux-gnu.so +0 -0
  161. package/src/zexus/vm/optimizer.py +161 -11
  162. package/src/zexus/vm/parallel_vm.py +140 -45
  163. package/src/zexus/vm/peephole_optimizer.py +82 -4
  164. package/src/zexus/vm/profiler.py +38 -18
  165. package/src/zexus/vm/register_allocator.py +16 -5
  166. package/src/zexus/vm/register_vm.py +8 -5
  167. package/src/zexus/vm/vm.py +3581 -531
  168. package/src/zexus/vm/wasm_compiler.py +658 -0
  169. package/src/zexus/zexus_ast.py +137 -11
  170. package/src/zexus/zexus_token.py +16 -5
  171. package/src/zexus/zpm/installer.py +55 -15
  172. package/src/zexus/zpm/package_manager.py +1 -1
  173. package/src/zexus/zpm/registry.py +257 -28
  174. package/src/zexus.egg-info/PKG-INFO +16 -6
  175. package/src/zexus.egg-info/SOURCES.txt +129 -17
  176. package/src/zexus.egg-info/entry_points.txt +1 -0
  177. package/src/zexus.egg-info/requires.txt +4 -0
@@ -0,0 +1,368 @@
1
+ """Resource loading utilities for the `load` keyword."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ from pathlib import Path
8
+ from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence
9
+
10
+
11
+ class LoadManager:
12
+ """Coordinates value lookups for the `load` keyword."""
13
+
14
+ def __init__(self, project_root: Optional[Path] = None) -> None:
15
+ self.project_root = Path(project_root or os.getcwd()).resolve()
16
+ self._providers: Dict[str, Callable[..., Any]] = {}
17
+ self._dotenv_cache: Dict[Path, Dict[str, Any]] = {}
18
+ self._structured_cache: Dict[tuple, Dict[str, Any]] = {}
19
+ self._register_defaults()
20
+
21
+ # ------------------------------------------------------------------
22
+ # Provider registration
23
+ # ------------------------------------------------------------------
24
+
25
+ def _register_defaults(self) -> None:
26
+ self.register_provider("env", self._load_from_env)
27
+ self.register_provider("dotenv", self._load_from_dotenv)
28
+ self.register_provider("file", self._load_from_file)
29
+
30
+ def register_provider(self, name: str, handler: Callable[..., Any]) -> None:
31
+ self._providers[name.lower()] = handler
32
+
33
+ def unregister_provider(self, name: str) -> None:
34
+ self._providers.pop(name.lower(), None)
35
+
36
+ def available_providers(self) -> Sequence[str]:
37
+ return tuple(self._providers.keys())
38
+
39
+ def is_provider_registered(self, name: Optional[str]) -> bool:
40
+ return bool(name) and name.lower() in self._providers
41
+
42
+ # ------------------------------------------------------------------
43
+ # Public load API
44
+ # ------------------------------------------------------------------
45
+
46
+ def load(
47
+ self,
48
+ key: str,
49
+ *,
50
+ provider: Optional[str] = None,
51
+ source: Optional[str] = None,
52
+ current_dir: Optional[str] = None,
53
+ ) -> Any:
54
+ """Resolve a value using registered providers and fallbacks."""
55
+
56
+ provider_name = provider.lower() if provider else None
57
+ if provider_name:
58
+ handler = self._providers.get(provider_name)
59
+ if not handler:
60
+ raise KeyError(f"Unknown provider '{provider}'")
61
+ value = handler(
62
+ key,
63
+ source=source,
64
+ current_dir=current_dir,
65
+ explicit=True,
66
+ )
67
+ if value is None:
68
+ raise KeyError(key)
69
+ return value
70
+
71
+ # Default lookup chain
72
+ value = self._load_from_env(key)
73
+ if value is not None:
74
+ return value
75
+
76
+ value = self._load_from_dotenv(
77
+ key,
78
+ source=source,
79
+ current_dir=current_dir,
80
+ )
81
+ if value is not None:
82
+ return value
83
+
84
+ if source:
85
+ value = self._load_from_file(
86
+ key,
87
+ source,
88
+ current_dir=current_dir,
89
+ explicit=True,
90
+ )
91
+ if value is not None:
92
+ return value
93
+
94
+ raise KeyError(key)
95
+
96
+ def clear_caches(self) -> None:
97
+ self._dotenv_cache.clear()
98
+ self._structured_cache.clear()
99
+
100
+ # ------------------------------------------------------------------
101
+ # Provider helpers
102
+ # ------------------------------------------------------------------
103
+
104
+ def _load_from_env(
105
+ self,
106
+ key: str,
107
+ *,
108
+ source: Optional[str] = None,
109
+ current_dir: Optional[str] = None,
110
+ explicit: bool | None = None,
111
+ ) -> Optional[str]:
112
+ if not key:
113
+ return None
114
+
115
+ for candidate in self._key_variants(key):
116
+ value = os.environ.get(candidate)
117
+ if value is not None:
118
+ return value
119
+ return None
120
+
121
+ def _load_from_dotenv(
122
+ self,
123
+ key: str,
124
+ *,
125
+ source: Optional[str] = None,
126
+ current_dir: Optional[str] = None,
127
+ explicit: bool | None = None,
128
+ ) -> Optional[str]:
129
+ candidates: List[Path] = []
130
+
131
+ if source:
132
+ resolved = self._resolve_source(source, current_dir)
133
+ if resolved and resolved.is_file():
134
+ candidates.append(resolved)
135
+
136
+ if not explicit:
137
+ # Current directory .env
138
+ if current_dir:
139
+ candidates.append(Path(current_dir) / ".env")
140
+ # Project root .env
141
+ candidates.append(self.project_root / ".env")
142
+
143
+ for path in candidates:
144
+ mapping = self._load_dotenv_file(path)
145
+ if not mapping:
146
+ continue
147
+ value = self._lookup_mapping(mapping, key)
148
+ if value is not None:
149
+ return value
150
+ return None
151
+
152
+ def _load_from_file(
153
+ self,
154
+ key: str,
155
+ source: str,
156
+ *,
157
+ current_dir: Optional[str] = None,
158
+ explicit: bool | None = None,
159
+ ) -> Any:
160
+ resolved = self._resolve_source(source, current_dir)
161
+ if not resolved:
162
+ raise FileNotFoundError(source)
163
+
164
+ if resolved.is_dir():
165
+ # Allow pointing at directory containing .env
166
+ env_candidate = resolved / ".env"
167
+ return self._load_from_dotenv(
168
+ key,
169
+ source=str(env_candidate),
170
+ current_dir=current_dir,
171
+ explicit=True,
172
+ )
173
+
174
+ suffix = resolved.suffix.lower()
175
+ if suffix in (".env", ""):
176
+ return self._load_from_dotenv(
177
+ key,
178
+ source=str(resolved),
179
+ current_dir=current_dir,
180
+ explicit=True,
181
+ )
182
+
183
+ if suffix in (".json", ".jsn"):
184
+ data = self._load_json_file(resolved)
185
+ return self._extract_from_data(data, key)
186
+
187
+ if suffix in (".yaml", ".yml"):
188
+ try:
189
+ import yaml # type: ignore
190
+ except ImportError as exc: # pragma: no cover - optional dependency
191
+ raise FileNotFoundError(
192
+ f"YAML support requires PyYAML to be installed: {resolved}"
193
+ ) from exc
194
+ data = self._load_yaml_file(resolved, yaml)
195
+ return self._extract_from_data(data, key)
196
+
197
+ if not key:
198
+ return resolved.read_text(encoding="utf-8")
199
+ return None
200
+
201
+ # ------------------------------------------------------------------
202
+ # File helpers
203
+ # ------------------------------------------------------------------
204
+
205
+ def _resolve_source(
206
+ self,
207
+ source: str,
208
+ current_dir: Optional[str],
209
+ ) -> Optional[Path]:
210
+ candidate = Path(source)
211
+ search_order: Iterable[Path]
212
+
213
+ if candidate.is_absolute():
214
+ search_order = (candidate,)
215
+ else:
216
+ search_order = filter(
217
+ None,
218
+ (
219
+ Path(current_dir) / candidate if current_dir else None,
220
+ self.project_root / candidate,
221
+ ),
222
+ )
223
+
224
+ for root in search_order:
225
+ try:
226
+ resolved = root.resolve()
227
+ except (OSError, RuntimeError):
228
+ continue
229
+ if resolved.exists():
230
+ return resolved
231
+ return candidate.resolve() if candidate.exists() else None
232
+
233
+ def _load_dotenv_file(self, path: Path) -> Optional[Dict[str, str]]:
234
+ if not path or not path.exists() or not path.is_file():
235
+ return None
236
+
237
+ try:
238
+ mtime = path.stat().st_mtime_ns
239
+ except (OSError, AttributeError):
240
+ mtime = None
241
+
242
+ cache = self._dotenv_cache.get(path)
243
+ if cache and cache.get("mtime") == mtime:
244
+ return cache.get("data")
245
+
246
+ data: Dict[str, str] = {}
247
+ try:
248
+ with path.open("r", encoding="utf-8") as handle:
249
+ for line in handle:
250
+ stripped = line.strip()
251
+ if not stripped or stripped.startswith("#"):
252
+ continue
253
+ if "=" not in stripped:
254
+ continue
255
+ key, raw_value = stripped.split("=", 1)
256
+ value = raw_value.strip().strip('"').strip("'")
257
+ data[key.strip()] = value
258
+ except OSError:
259
+ return None
260
+
261
+ self._dotenv_cache[path] = {"mtime": mtime, "data": data}
262
+ return data
263
+
264
+ def _load_json_file(self, path: Path) -> Any:
265
+ try:
266
+ mtime = path.stat().st_mtime_ns
267
+ except (OSError, AttributeError):
268
+ mtime = None
269
+
270
+ cache = self._structured_cache.get((path, "json"))
271
+ if cache and cache.get("mtime") == mtime:
272
+ return cache.get("data")
273
+
274
+ with path.open("r", encoding="utf-8") as handle:
275
+ data = json.load(handle)
276
+
277
+ self._structured_cache[(path, "json")] = {"mtime": mtime, "data": data}
278
+ return data
279
+
280
+ def _load_yaml_file(self, path: Path, yaml_module) -> Any: # pragma: no cover - optional dependency
281
+ try:
282
+ mtime = path.stat().st_mtime_ns
283
+ except (OSError, AttributeError):
284
+ mtime = None
285
+
286
+ cache = self._structured_cache.get((path, "yaml"))
287
+ if cache and cache.get("mtime") == mtime:
288
+ return cache.get("data")
289
+
290
+ with path.open("r", encoding="utf-8") as handle:
291
+ data = yaml_module.safe_load(handle)
292
+
293
+ self._structured_cache[(path, "yaml")] = {"mtime": mtime, "data": data}
294
+ return data
295
+
296
+ # ------------------------------------------------------------------
297
+ # Lookup helpers
298
+ # ------------------------------------------------------------------
299
+
300
+ def _lookup_mapping(self, mapping: Dict[str, Any], key: str) -> Optional[str]:
301
+ for candidate in self._key_variants(key):
302
+ value = mapping.get(candidate)
303
+ if value is not None:
304
+ return value
305
+ return None
306
+
307
+ def _extract_from_data(self, data: Any, key: str) -> Any:
308
+ if key is None:
309
+ return data
310
+ if not key:
311
+ return data
312
+
313
+ parts = key.split(".")
314
+ current = data
315
+ for part in parts:
316
+ if isinstance(current, dict):
317
+ if part in current:
318
+ current = current[part]
319
+ continue
320
+ alt = part.replace("-", "_")
321
+ if alt in current:
322
+ current = current[alt]
323
+ continue
324
+ alt_upper = alt.upper()
325
+ if alt_upper in current:
326
+ current = current[alt_upper]
327
+ continue
328
+ return None
329
+ if isinstance(current, list):
330
+ try:
331
+ index = int(part)
332
+ except ValueError:
333
+ return None
334
+ if 0 <= index < len(current):
335
+ current = current[index]
336
+ continue
337
+ return None
338
+ return None
339
+ return current
340
+
341
+ def _key_variants(self, key: str) -> List[str]:
342
+ variants = {key, key.lower(), key.upper()}
343
+ if "." in key:
344
+ collapsed = key.replace(".", "_")
345
+ variants.add(collapsed)
346
+ variants.add(collapsed.lower())
347
+ variants.add(collapsed.upper())
348
+ if "-" in key:
349
+ hyphenless = key.replace("-", "_")
350
+ variants.add(hyphenless)
351
+ variants.add(hyphenless.lower())
352
+ variants.add(hyphenless.upper())
353
+ return [variant for variant in variants if variant]
354
+
355
+
356
+ _manager = LoadManager()
357
+
358
+
359
+ def get_load_manager() -> LoadManager:
360
+ return _manager
361
+
362
+
363
+ def register_provider(name: str, handler: Callable[..., Any]) -> None:
364
+ _manager.register_provider(name, handler)
365
+
366
+
367
+ def clear_load_caches() -> None:
368
+ _manager.clear_caches()