Coverage for  / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / codegen / cli.py: 96%

47 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-11-15 07:18 +0800

1# Copyright 2026 Huawei Technologies Co., Ltd 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14# ============================================================================ 

15"""Thin command-line interface for native-build codegen workflows.""" 

16 

17from __future__ import annotations 

18 

19import argparse 

20import logging 

21import os 

22import sys 

23from typing import Optional 

24 

25from hyper_parallel.codegen.build import generate_from_native_build 

26from hyper_parallel.trainer.config import parser as config_parser 

27 

28logger = logging.getLogger(__name__) 

29 

30 

31def main(argv: Optional[list[str]] = None) -> int: 

32 """Run the CLI and return its process exit code.""" 

33 parser = _build_parser() 

34 args, config_overrides = parser.parse_known_args(argv) 

35 setattr(args, "_config_overrides", config_overrides) 

36 if not getattr(args, "command", None): 

37 parser.print_usage(sys.stderr) 

38 return 2 

39 _configure_logging(getattr(args, "verbose", False)) 

40 try: 

41 return args.func(args) 

42 except Exception as exc: # A CLI reports failures without a traceback by default. 

43 if getattr(args, "verbose", False): 

44 logger.exception("codegen: %s", exc) 

45 else: 

46 logger.error("codegen: %s", exc) 

47 return 1 

48 

49 

50def cmd_generate(args: argparse.Namespace) -> int: 

51 """Observe a meta model and generate a fresh bundle.""" 

52 if int(os.environ.get("WORLD_SIZE", "1")) > 1: 

53 raise RuntimeError( 

54 "codegen generate is a single-process CPU/meta command; " 

55 "run it with python instead of torchrun" 

56 ) 

57 config = _load_config(args.config, _cli_overrides(args)) 

58 layout = generate_from_native_build(config, artifact_dir=args.output) 

59 logger.info("codegen: artifact %s", layout.artifact_dir) 

60 return 0 

61 

62 

63def _load_config(yaml_path: str, overrides: Optional[list[str]] = None): 

64 """Load a resolved TrainerConfig without building trainer runtime components.""" 

65 return config_parser.load_training_config(yaml_path, overrides or []) 

66 

67 

68def _cli_overrides(args: argparse.Namespace) -> list[str]: 

69 """Return typed config overrides left after argparse processing.""" 

70 return list(getattr(args, "_config_overrides", None) or []) 

71 

72 

73def _configure_logging(verbose: bool) -> None: 

74 logging.basicConfig( 

75 level=logging.INFO if verbose else logging.WARNING, 

76 format="%(levelname)s:%(name)s:%(message)s", 

77 ) 

78 

79 

80def _build_parser() -> argparse.ArgumentParser: 

81 """Build the codegen command-line parser.""" 

82 parser = argparse.ArgumentParser( 

83 prog="hyper_parallel.codegen", 

84 description="Generate a model bundle from a training YAML.", 

85 ) 

86 parser.add_argument("--verbose", action="store_true", help="verbose logging") 

87 subparsers = parser.add_subparsers(dest="command") 

88 

89 generate = subparsers.add_parser( 

90 "generate", 

91 help="observe the model on meta and generate its bundle", 

92 ) 

93 generate.add_argument("--config", required=True, help="path to the training YAML") 

94 generate.add_argument("--output", help="explicit artifact output directory") 

95 generate.set_defaults(func=cmd_generate) 

96 

97 return parser 

98 

99 

100__all__ = ["cmd_generate", "main"]