Coverage for lobster/tools/core/online_report_nogit/online_report_nogit.py: 100%

47 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2025-08-06 09:51 +0000

1import argparse 

2import os 

3import sys 

4 

5from dataclasses import dataclass 

6from typing import Iterable 

7from urllib.parse import quote 

8 

9from lobster.items import Item 

10from lobster.location import File_Reference, Github_Reference 

11from lobster.report import Report 

12from lobster.meta_data_tool_base import MetaDataToolBase 

13 

14 

15@dataclass 

16class RepoInfo: 

17 """ 

18 Data class to hold repository information. 

19 

20 Attributes: 

21 remote_url (str): The root URL of the GitHub repository. 

22 root (str): The local path to the root of the repository. 

23 commit (str): The commit hash to use when building a URL to a file. 

24 """ 

25 remote_url: str 

26 root: str 

27 commit: str 

28 

29 

30def _file_ref_to_github_ref( 

31 file_ref: File_Reference, 

32 repo_info: RepoInfo, 

33 paths_must_exist: bool, 

34) -> Github_Reference: 

35 """ 

36 Convert a File_Reference to a Github_Reference. 

37 

38 Args: 

39 file_ref (File_Reference): The file reference to convert (can be a directory). 

40 repo_data (RepoData): The repository meta information to use for the conversion. 

41 paths_must_exist (bool): If True, then a sanity check is performed. If the path 

42 is is not a directory and not a file, then a FileNotFoundError is raised. 

43 

44 Returns: 

45 Github_Reference: The converted GitHub reference. 

46 """ 

47 if (not paths_must_exist) \ 

48 or os.path.isfile(file_ref.filename) or os.path.isdir(file_ref.filename): 

49 return Github_Reference( 

50 gh_root=repo_info.remote_url, 

51 filename=quote( 

52 os.path.relpath( 

53 os.path.realpath(file_ref.filename), 

54 os.path.realpath(repo_info.root), 

55 ).replace(os.sep, "/") 

56 ), 

57 line=file_ref.line, 

58 commit=repo_info.commit, 

59 ) 

60 raise FileNotFoundError(f"File '{file_ref.filename}' does not exist.") 

61 

62 

63def _update_items(items: Iterable[Item], repo_info: RepoInfo, paths_must_exist: bool): 

64 for item in items: 

65 if isinstance(item.location, File_Reference): 

66 item.location = _file_ref_to_github_ref( 

67 item.location, 

68 repo_info, 

69 paths_must_exist, 

70 ) 

71 

72 

73def apply_github_urls( 

74 in_file: str, 

75 out_file: str, 

76 repository_info: RepoInfo, 

77 paths_must_exist: bool = True): 

78 """ 

79 Reads a report file, converts all file references to GitHub references, 

80 and saves the report. 

81 

82 Args: 

83 file (str): Path to the input LOBSTER report file. 

84 out_file (str): Output file for the updated LOBSTER report. 

85 repo_data (RepoData): object containing remote URL, root path, and commit hash. 

86 paths_must_exist (bool): If True, then a sanity check is performed. If the path 

87 is is not a directory and not a file, then a FileNotFoundError is raised. 

88 """ 

89 report = Report() 

90 report.load_report(in_file) 

91 _update_items(report.items.values(), repository_info, paths_must_exist) 

92 report.write_report(out_file) 

93 

94 

95class OnlineReportNogitTool(MetaDataToolBase): 

96 def __init__(self): 

97 super().__init__( 

98 name="lobster-online-report-nogit", 

99 description="Update file locations in LOBSTER report to GitHub references.", 

100 official=True, 

101 ) 

102 ap = self._argument_parser 

103 ap.add_argument(dest="report", 

104 metavar="LOBSTER_REPORT", 

105 help="Path to the input LOBSTER report file.") 

106 ap.add_argument("--repo-root", required=True, 

107 help="Local path to the root of the repository.") 

108 ap.add_argument("--remote-url", required=True, 

109 help="GitHub repository root URL.") 

110 ap.add_argument("--commit", required=True, 

111 help="Git commit hash to use for the references.") 

112 ap.add_argument("--out", required=True, metavar="OUTPUT_FILE", 

113 help="Output file for the updated LOBSTER report." 

114 "It can be the same as the input file in order to " 

115 "overwrite the input file.",) 

116 

117 def _run_impl(self, options: argparse.Namespace) -> int: 

118 try: 

119 apply_github_urls( 

120 in_file=options.report, 

121 repository_info=RepoInfo( 

122 remote_url=options.remote_url, 

123 root=options.repo_root, 

124 commit=options.commit, 

125 ), 

126 out_file=options.out, 

127 ) 

128 print(f"LOBSTER report {options.out} created, using remote URL references.") 

129 except FileNotFoundError as e: 

130 print( 

131 f"Error: {e}\n" 

132 f"Note: Relative paths are resolved with respect to the " 

133 f"current working directory '{os.getcwd()}'.", 

134 file=sys.stderr, 

135 ) 

136 return 1 

137 return 0 

138 

139 

140def main() -> int: 

141 return OnlineReportNogitTool().run()