Skip to content

Commit 24afe88

Browse files
committed
Korbit review comments
1 parent d35e495 commit 24afe88

8 files changed

Lines changed: 82 additions & 41 deletions

File tree

dfetch/manifest/manifest.py

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import os
2424
import pathlib
2525
import re
26+
from dataclasses import dataclass
2627
from typing import IO, Any, Dict, List, Optional, Sequence, Tuple, Union
2728

2829
import yaml
@@ -38,6 +39,15 @@
3839
logger = get_logger(__name__)
3940

4041

42+
@dataclass
43+
class ManifestEntryLocation:
44+
"""Location of an entry in the manifest file."""
45+
46+
line_number: int
47+
start: int
48+
end: int
49+
50+
4151
class RequestedProjectNotFoundError(RuntimeError):
4252
"""Exception if items are not found in list of possibilities."""
4353

@@ -111,8 +121,8 @@ def __init__(
111121
) -> None:
112122
"""Create the manifest."""
113123
self.__version: str = str(manifest.get("version", self.CURRENT_VERSION))
114-
self.__text: str = str(text)
115-
self.__path: str = str(path)
124+
self.__text: str = text if text else ""
125+
self.__path: str = str(path) if path else ""
116126

117127
self._remotes, default_remotes = self._determine_remotes(
118128
manifest.get("remotes", [])
@@ -193,6 +203,9 @@ def from_yaml(
193203
path: Optional[Union[str, os.PathLike[str]]] = None,
194204
) -> "Manifest":
195205
"""Create a manifest from a file like object."""
206+
if isinstance(text, (io.TextIOWrapper, IO)):
207+
text = text.read()
208+
196209
loaded_yaml = Manifest._load_yaml(text)
197210

198211
if not loaded_yaml:
@@ -203,10 +216,6 @@ def from_yaml(
203216
if not manifest:
204217
raise RuntimeError("Missing manifest root element!")
205218

206-
if isinstance(text, (io.TextIOWrapper, IO)):
207-
text.seek(0)
208-
text = text.read()
209-
210219
return Manifest(manifest, text=text, path=path)
211220

212221
@staticmethod
@@ -313,24 +322,29 @@ def dump(self, path: str) -> None:
313322
self._as_dict(), manifest_file, Dumper=ManifestDumper, sort_keys=False
314323
)
315324

316-
def find_name_in_manifest(self, name: str) -> Tuple[int, int, int]:
317-
"""Find the location of a project name in the manifest."""
325+
def find_name_in_manifest(self, name: str) -> ManifestEntryLocation:
326+
"""Find the location of a project name in the manifest.
327+
328+
Returns:
329+
ManifestEntryLocation of the project name in the manifest.
330+
331+
Raises:
332+
FileNotFoundError: If manifest text is not available
333+
RuntimeError: If the project name is not found in the manifest
334+
"""
318335
if not self.__text:
319336
raise FileNotFoundError("No manifest text available")
320337

321338
for line_nr, line in enumerate(self.__text.splitlines(), start=1):
322-
match = re.search(rf"^\s+-\s*name:\s*(?P<name>{name})\s*$", line)
339+
match = re.search(rf"^\s+-\s*name:\s*(?P<name>{re.escape(name)})\s*$", line)
323340

324341
if match:
325-
return (
326-
line_nr,
327-
int(match.start("name")) + 1,
328-
int(match.end("name")),
342+
return ManifestEntryLocation(
343+
line_number=line_nr,
344+
start=int(match.start("name")) + 1,
345+
end=int(match.end("name")),
329346
)
330-
raise RuntimeError(
331-
"An entry from the manifest was provided,"
332-
" that doesn't exist in the manifest!"
333-
)
347+
raise RuntimeError(f"{name} was not found in the manifest!")
334348

335349

336350
def find_manifest() -> str:

dfetch/reporting/check/code_climate_reporter.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def add_issue(self, project: ProjectEntry, issue: Issue) -> None:
112112
project (ProjectEntry): Project with the issue
113113
issue (Issue): The issue to add to the report
114114
"""
115-
line, col_start, col_end = self._manifest.find_name_in_manifest(project.name)
115+
location = self._manifest.find_name_in_manifest(project.name)
116116

117117
self._report += [
118118
{
@@ -126,8 +126,11 @@ def add_issue(self, project: ProjectEntry, issue: Issue) -> None:
126126
"location": {
127127
"path": os.path.relpath(self._manifest.path),
128128
"positions": {
129-
"begin": {"line": line, "column": col_start},
130-
"end": {"line": line, "column": col_end},
129+
"begin": {
130+
"line": location.line_number,
131+
"column": location.start,
132+
},
133+
"end": {"line": location.line_number, "column": location.end},
131134
},
132135
},
133136
}

dfetch/reporting/check/jenkins_reporter.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,17 @@ def add_issue(self, project: ProjectEntry, issue: Issue) -> None:
9090
project (ProjectEntry): Project with the issue
9191
issue (Issue): The issue to add to the report
9292
"""
93-
line, col_start, col_end = self._manifest.find_name_in_manifest(project.name)
93+
location = self._manifest.find_name_in_manifest(project.name)
9494
self._report["issues"] += [
9595
{
9696
"fileName": os.path.relpath(self._manifest.path),
9797
"severity": str(issue.severity.value),
9898
"message": f"{project.name} : {issue.message}",
9999
"description": issue.description,
100-
"lineStart": line,
101-
"lineEnd": line,
102-
"columnStart": col_start,
103-
"columnEnd": col_end,
100+
"lineStart": location.line_number,
101+
"lineEnd": location.line_number,
102+
"columnStart": location.start,
103+
"columnEnd": location.end,
104104
}
105105
]
106106

dfetch/reporting/check/sarif_reporter.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def add_issue(self, project: ProjectEntry, issue: Issue) -> None:
177177
project (ProjectEntry): Project with the issue
178178
issue (Issue): The issue to add
179179
"""
180-
line, col_start, col_end = self._manifest.find_name_in_manifest(project.name)
180+
location = self._manifest.find_name_in_manifest(project.name)
181181

182182
result = Result(
183183
message=Message(text=f"{project.name} : {issue.message}"),
@@ -190,10 +190,10 @@ def add_issue(self, project: ProjectEntry, issue: Issue) -> None:
190190
uri=os.path.relpath(self._manifest.path), index=0
191191
),
192192
region=Region(
193-
start_line=line,
194-
start_column=col_start,
195-
end_line=line,
196-
end_column=col_end + 1,
193+
start_line=location.line_number,
194+
start_column=location.start,
195+
end_line=location.line_number,
196+
end_column=location.end + 1,
197197
),
198198
)
199199
)

dfetch/reporting/reporter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ class Reporter(ABC):
1313

1414
name: str = "abstract"
1515

16+
@abstractmethod
1617
def __init__(self, manifest: Manifest) -> None:
1718
"""Create the reporter.
1819
1920
Args:
2021
manifest (Manifest): The manifest to report on
2122
"""
22-
self._manifest = manifest
2323

2424
@abstractmethod
2525
def add_project(

dfetch/reporting/sbom_reporter.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class SbomReporter(Reporter):
102102

103103
def __init__(self, manifest: Manifest) -> None:
104104
"""Start the report."""
105-
super().__init__(manifest)
105+
self._manifest = manifest
106106
self._bom = Bom()
107107
self._bom.metadata.tools.components.add(self.dfetch_tool)
108108
self._bom.metadata.tools.components.add(cdx_lib_component())
@@ -120,7 +120,7 @@ def add_project(
120120

121121
name = project.name if purl.type == "generic" else purl.name
122122

123-
line_nr, start, _ = self._manifest.find_name_in_manifest(project.name)
123+
location = self._manifest.find_name_in_manifest(project.name)
124124

125125
component = Component(
126126
name=name,
@@ -130,7 +130,11 @@ def add_project(
130130
purl=purl,
131131
evidence=ComponentEvidence(
132132
occurrences=[
133-
Occurrence(location=self._manifest.path, line=line_nr, offset=start)
133+
Occurrence(
134+
location=self._manifest.path,
135+
line=location.line_number,
136+
offset=location.start,
137+
)
134138
],
135139
identity=[
136140
Identity(

dfetch/reporting/stdout_reporter.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing import List
88

99
from dfetch.log import get_logger
10+
from dfetch.manifest.manifest import Manifest
1011
from dfetch.manifest.project import ProjectEntry
1112
from dfetch.project.metadata import Metadata
1213
from dfetch.reporting.reporter import Reporter
@@ -20,6 +21,10 @@ class StdoutReporter(Reporter):
2021

2122
name = "stdout"
2223

24+
def __init__(self, manifest: Manifest) -> None:
25+
"""Initialize the reporter."""
26+
del manifest
27+
2328
def add_project(
2429
self,
2530
project: ProjectEntry,

dfetch/util/license.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,36 @@
77
import infer_license
88
from infer_license.types import License as InferredLicense
99

10+
# Limit the max size of alicense file to parse
11+
MAX_LICENSE_FILE_SIZE = 1024 * 1024
12+
1013

1114
@dataclass
1215
class License:
13-
"""Class to hold license information."""
16+
"""Represents a software license with its SPDX identifiers and detection confidence.
17+
18+
This class encapsulates license information detected by the infer-license library,
19+
providing standardized identifiers and confidence level of the detection.
20+
"""
1421

15-
name: str # SPDX Full name
16-
spdx_id: str # SPDX Identifier
17-
trove_classifier: Optional[str] # Python package classifier
18-
probability: float # Confidence level of the license inference
22+
name: str #: SPDX Full name
23+
spdx_id: str #: SPDX Identifier
24+
trove_classifier: Optional[str] #: Python package classifier
25+
probability: float #: Confidence level of the license inference
1926

2027
@staticmethod
2128
def from_inferred(
2229
inferred_license: InferredLicense, probability: float
2330
) -> "License":
24-
"""Create License from an InferredLicense."""
31+
"""Convert an infer-license License object to our internal License representation.
32+
33+
Args:
34+
inferred_license: The license object from infer-license library
35+
probability: The confidence score (0-1) of the license detection
36+
37+
Returns:
38+
License: A new License instance with the inferred information
39+
"""
2540
return License(
2641
name=inferred_license.name,
2742
spdx_id=inferred_license.shortname,
@@ -43,7 +58,7 @@ def guess_license_in_file(
4358
"""
4459
try:
4560
with open(filename, "rb") as f:
46-
file_bytes = f.read()
61+
file_bytes = f.read(MAX_LICENSE_FILE_SIZE)
4762
try:
4863
license_text = file_bytes.decode("utf-8")
4964
except UnicodeDecodeError:

0 commit comments

Comments
 (0)