Coverage for lobster/tools/core/online_report_nogit/online_report_nogit.py: 51%
47 statements
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-06 09:51 +0000
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-06 09:51 +0000
1import argparse
2import os
3import sys
5from dataclasses import dataclass
6from typing import Iterable
7from urllib.parse import quote
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
15@dataclass
16class RepoInfo:
17 """
18 Data class to hold repository information.
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
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.
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.
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.")
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 )
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.
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)
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.",)
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
140def main() -> int:
141 return OnlineReportNogitTool().run()