Coverage for src / mysingle / cli / protos / commands / status.py: 0%

54 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-12-02 00:58 +0900

1""" 

2Status 명령 - 서비스별 proto 파일 상태 확인. 

3""" 

4 

5from __future__ import annotations 

6 

7import argparse 

8 

9from ..models import ProtoConfig, ServiceProtoInfo 

10from ..utils import Color, LogLevel, colorize, log, log_header, log_table 

11 

12 

13def discover_services(config: ProtoConfig) -> list[ServiceProtoInfo]: 

14 """서비스 디렉터리에서 proto 정보 스캔""" 

15 if not config.services_root.exists(): 

16 # 서비스 submodule에서 실행한 경우 빈 리스트 반환 

17 return [] 

18 

19 log_header("서비스 스캔") 

20 result: list[ServiceProtoInfo] = [] 

21 skipped = 0 

22 

23 for service_dir in sorted(p for p in config.services_root.iterdir() if p.is_dir()): 

24 proto_dir = service_dir / "protos" 

25 if not proto_dir.exists(): 

26 log( 

27 f"건너뛰기: {colorize(service_dir.name, Color.DIM)} (protos 디렉터리 없음)", 

28 LogLevel.WARNING, 

29 ) 

30 skipped += 1 

31 continue 

32 files = sorted(proto_dir.rglob("*.proto")) 

33 if not files: 

34 log( 

35 f"건너뛰기: {colorize(service_dir.name, Color.DIM)} (proto 파일 없음)", 

36 LogLevel.WARNING, 

37 ) 

38 skipped += 1 

39 continue 

40 result.append(ServiceProtoInfo(service_dir.name, service_dir, proto_dir, files)) 

41 log( 

42 f"발견: {colorize(service_dir.name, Color.GREEN)} ({len(files)}개 파일)", 

43 LogLevel.SUCCESS, 

44 ) 

45 

46 log( 

47 f"\n총 {colorize(str(len(result)), Color.BRIGHT_GREEN, bold=True)}개 서비스 발견 (건너뜀: {skipped}개)", 

48 LogLevel.INFO, 

49 ) 

50 return result 

51 

52 

53def execute(args: argparse.Namespace, config: ProtoConfig) -> int: 

54 """Status 명령 실행""" 

55 # Submodule 내에서 실행 시 경고 

56 if not config.services_root.exists(): 

57 log( 

58 "⚠️ 이 명령은 grpc-protos 메인 저장소에서만 사용할 수 있습니다.", 

59 LogLevel.WARNING, 

60 ) 

61 log( 

62 "서비스 디렉터리의 submodule에서는 'proto-cli version' 또는 'proto-cli validate'를 사용하세요.", 

63 LogLevel.INFO, 

64 ) 

65 return 1 

66 

67 services = discover_services(config) 

68 

69 if not services: 

70 log("발견된 서비스가 없습니다.", LogLevel.WARNING) 

71 return 1 

72 

73 log_header("서비스별 Proto 파일 현황") 

74 

75 rows = [] 

76 for service in services: 

77 rows.append([service.name, str(len(service.files)), str(service.proto_dir)]) 

78 

79 log_table(["서비스 이름", "Proto 파일 수", "경로"], rows) 

80 

81 # 상세 모드 

82 if args.verbose: 

83 log_header("Proto 파일 상세 목록") 

84 for service in services: 

85 print(f"\n{colorize(service.name, Color.BRIGHT_CYAN, bold=True)}:") 

86 for proto_file in service.files: 

87 rel_path = proto_file.relative_to(service.proto_dir) 

88 print(f"{rel_path}") 

89 

90 return 0 

91 

92 

93def execute_interactive(config: ProtoConfig) -> int: 

94 """대화형 모드로 status 명령 실행""" 

95 from ...utils import ask_confirm 

96 

97 # 상세 모드 선택 

98 verbose = ask_confirm("Proto 파일 상세 목록을 표시하시겠습니까?", default=False) 

99 

100 args = argparse.Namespace(verbose=verbose) 

101 return execute(args, config) 

102 

103 

104def setup_parser(parser: argparse.ArgumentParser) -> None: 

105 """Status 명령 파서 설정""" 

106 parser.add_argument( 

107 "-v", 

108 "--verbose", 

109 action="store_true", 

110 help="Proto 파일 상세 목록 출력", 

111 )