56 """Result of the strategy pipeline, with a separately cached capability canary."""
58 generated_cpp: str |
None
59 inputs: tuple[dict[str, Any], ...] = ()
60 strategy_params: Mapping[str, Any] = field(default_factory=dict)
61 diagnostics: tuple[TranspileDiagnostic, ...] = ()
62 input_kind_schema: int |
None =
None
63 request_feed_inventory: Mapping[str, Any] |
None =
None
68 diagnostic.severity ==
"error" for diagnostic
in self.
diagnostics
219def transpile_source(pine_source: str, *, filename: str =
"<input>") -> TranspileResult:
220 """Transpile source once and normalize all expected diagnostics.
222 Pine language errors are returned in ``TranspileResult`` rather than being
223 conflated with native compiler failures. Unexpected bridge failures are also
224 represented as an ``INTERNAL`` diagnostic so a CLI can emit one stable JSON
225 envelope. When available, the inventory producer replaces ``transpile_full``
226 for this source. It stays chart-unbound; requests for the chart's timeframe
227 therefore remain unknown. The input-kind canary still uses its own source.
231 transpiler, compile_error = _load_codegen()
232 except ModuleNotFoundError:
238 phase=
"CONFIGURATION",
240 "pineforge-codegen is required to compile PineScript; "
241 "install pineforge-hpo[transpile] or provide a precompiled artifact"
249 strategy_transpiler = (
250 pineforge_codegen.transpile_with_request_inventory
251 if produces_inventory
255 payload = strategy_transpiler(pine_source, filename=filename)
256 except compile_error
as error:
259 diagnostics=tuple(_diagnostic_from_codegen(d)
for d
in error.diagnostics),
261 except Exception
as error:
268 message=f
"{type(error).__name__}: {error}",
274 if not isinstance(payload, Mapping):
281 message=
"transpile_full returned a non-object result",
287 cpp = payload.get(
"cpp")
288 inputs = payload.get(
"inputs", [])
289 strategy_params = payload.get(
"strategyParams", {})
291 not isinstance(cpp, str)
292 or not isinstance(inputs, list)
293 or not isinstance(strategy_params, Mapping)
301 message=
"transpile_full returned an invalid result shape",
307 normalized_inputs: list[dict[str, Any]] = []
309 if not isinstance(item, Mapping):
316 message=
"transpile_full input manifest contains a non-object entry",
321 normalized_inputs.append(dict(item))
323 inventory = payload.get(
"request_feed_inventory")
if produces_inventory
else None
324 if produces_inventory
and (
325 not isinstance(inventory, Mapping)
326 or inventory.get(
"schema") != REQUEST_FEED_INVENTORY_SCHEMA
335 "transpile_with_request_inventory returned an invalid "
336 "request_feed_inventory object or schema"
345 inputs=tuple(normalized_inputs),
346 strategy_params=dict(strategy_params),
347 diagnostics=_diagnostics_from_payload(payload),
350 if isinstance(payload.get(
"requests"), list)
351 and all(isinstance(item, Mapping)
for item
in payload[
"requests"])
352 and _input_kind_canary(transpiler)
355 request_feed_inventory=inventory,
372 """Return version plus a hash that detects dirty/editable codegen installs."""
374 _transpiler, _compile_error = _load_codegen()
375 assert pineforge_codegen
is not None
378 version = metadata.version(
"pineforge-codegen")
379 except metadata.PackageNotFoundError:
380 version = str(getattr(pineforge_codegen,
"__version__",
"unknown"))
382 module_file = Path(pineforge_codegen.__file__
or "").resolve()
383 package_root = module_file.parent
384 digest = hashlib.sha256()
386 sorted(package_root.rglob(
"*.py"))
if package_root.is_dir()
else [module_file]
389 if not path.is_file():
392 relative = path.relative_to(package_root).as_posix()
395 digest.update(relative.encode(
"utf-8"))
397 digest.update(path.read_bytes())
401 implementation_sha256=digest.hexdigest(),
402 module_path=str(module_file),