Coverage for / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / codegen / emit / bundle.py: 33%
39 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-25 05:45 +0800
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-25 05:45 +0800
1# Copyright 2026 Huawei Technologies Co., Ltd
2# Licensed under the Apache License, Version 2.0
3# ============================================================================
4"""Bundle emission: the entry the codegen manager calls to produce an artifact.
6``emit_bundle`` is what the manager calls: it is invoked as
7``emit_bundle(layout, meta)`` (manager.ensure_codegen_artifact) after the plan has
8been derived and frozen into ``meta``. So this layer never derives anything —
9it renders the already-frozen contract into a ``files`` dict
10(filename -> content), and the manager stages + atomically swaps the whole
11bundle (including ``codegen_meta.json``) in one directory switch.
13The whole bundle is written as one atomic unit: ``emit_bundle``
14returns the modeling file, its diff, and ``__init__.py`` as a dict, and
15``write_bundle_atomic`` stages them alongside the meta in a temp sibling then
16swaps the directory in. A half-written bundle can never be imported.
18``meta`` carries the frozen plan, resolved source, and parallel dimensions, so
19passing separate copies would create a second source of truth.
20"""
21from __future__ import annotations
23import logging
24import os
25from typing import Any
27from hyper_parallel.codegen.artifact import ArtifactLayout
28from hyper_parallel.codegen.emit.diff import unified_diff
29from hyper_parallel.codegen.emit.modeling import (
30 copy_original_modeling,
31 emit_modeling_file,
32)
34logger = logging.getLogger(__name__)
37def emit_bundle(layout: ArtifactLayout, meta: Any) -> dict[str, str]:
38 """Render the artifact bundle for one frozen ``meta``.
40 Manager-facing entry point. Returns a ``filename -> content`` dict
41 holding the generated modeling file, the unified diff against the original
42 source, and ``__init__.py``; the caller (manager) stages and atomically
43 swaps the bundle, then writes ``codegen_meta.json`` last inside the
44 staging dir.
46 ``meta.covered`` is prepared by the manager before emission.
47 """
48 original_text = copy_original_modeling(meta.source)
49 generated_text = emit_modeling_file(meta)
51 modeling_name = os.path.basename(layout.modeling_path)
52 diff_text = emit_diff(original_text, generated_text, layout)
54 logger.info(
55 "codegen: rendered bundle %s (modeling %s, %d plan boundaries)",
56 layout.artifact_dir,
57 modeling_name,
58 len(getattr(meta, "param_plan", None) or {}),
59 )
60 files = {
61 # Filename keys (not absolute paths): write_bundle_atomic stages them
62 # in a temp sibling and swaps the whole directory in.
63 modeling_name: generated_text,
64 os.path.basename(layout.diff_path): diff_text,
65 "__init__.py": emit_init_file(layout),
66 }
67 # A ``<remote>`` source is
68 # shipped inside the checkpoint and uses single-dot relative imports
69 # (``from .configuration_deepseek import ...``) that resolve against its
70 # own package. The loader compiles the generated file as the synthetic
71 # package ``hyper_parallel_generated.<digest>``, so those siblings must be
72 # IN the bundle and registered under that package. Copy the transitive
73 # closure of the source's relative imports here (original basenames), and
74 # record what was copied so preflight/loader can tell a stale bundle.
75 siblings: dict[str, str] = {}
76 source_obj = meta.source
77 source_module = (
78 source_obj.get("module_name") if isinstance(source_obj, dict)
79 else getattr(source_obj, "module_name", None)
80 )
81 if source_module == "<remote>":
82 from hyper_parallel.codegen.source.resolver import resolve_remote_siblings
84 resolved = resolve_remote_siblings(source_obj)
85 for path in resolved.values():
86 basename = os.path.basename(path)
87 with open(path, "r", encoding="utf-8", errors="replace") as handle:
88 siblings[basename] = handle.read()
89 files.update(siblings)
90 if siblings:
91 meta.remote_siblings = sorted(siblings)
92 return files
95def emit_init_file(layout: ArtifactLayout) -> str:
96 """Render the bundle's ``__init__.py`` text.
98 The bundle is imported by file location (loader.import_generated_module),
99 not as a package, so this file carries no re-exports — it only marks the
100 directory and records what the bundle is for a reader who opens it.
101 """
102 return (
103 '"""Generated codegen bundle — DO NOT EDIT MANUALLY.\n'
104 "\n"
105 f"Generated from: {layout.yaml_path}\n"
106 "Regenerate by re-running training with ``codegen: true``; the bundle\n"
107 "is rebuilt whenever the codegen signature changes.\n"
108 '"""\n'
109 )
112def emit_diff(original_text: str, generated_text: str, layout: ArtifactLayout) -> str:
113 """Render the unified diff from the original source to the generated file.
115 Returned rather than written so ``emit_bundle`` can write the whole bundle
116 in one atomic call.
117 """
118 return unified_diff(
119 original_text,
120 generated_text,
121 fromfile=f"a/{_source_basename(layout)}",
122 tofile=f"b/{os.path.basename(layout.modeling_path)}",
123 )
126def _source_basename(layout: ArtifactLayout) -> str:
127 """Diff ``fromfile`` label: the original modeling filename."""
128 name = os.path.basename(layout.modeling_path)
129 if name.endswith("_gen_npu.py"):
130 return name[: -len("_gen_npu.py")] + ".py"
131 return name
134__all__ = [
135 "emit_bundle",
136 "emit_diff",
137 "emit_init_file",
138 "emit_modeling_file",
139]