Skip to content

Commit 0de8e2b

Browse files
committed
Move manifest path & text location into Manifest class
1 parent 4ee5bbe commit 0de8e2b

18 files changed

Lines changed: 125 additions & 133 deletions

dfetch/commands/check.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import dfetch.project
3030
from dfetch.commands.common import check_child_manifests
3131
from dfetch.log import get_logger
32+
from dfetch.manifest.manifest import Manifest
3233
from dfetch.reporting.check.code_climate_reporter import CodeClimateReporter
3334
from dfetch.reporting.check.jenkins_reporter import JenkinsReporter
3435
from dfetch.reporting.check.reporter import CheckReporter
@@ -83,18 +84,18 @@ def create_menu(subparsers: dfetch.commands.command.SubparserActionType) -> None
8384

8485
def __call__(self, args: argparse.Namespace) -> None:
8586
"""Perform the check."""
86-
manifest, path = dfetch.manifest.manifest.get_manifest()
87-
reporters = self._get_reporters(args, path)
87+
manifest = dfetch.manifest.manifest.get_manifest()
88+
reporters = self._get_reporters(args, manifest)
8889

89-
with in_directory(os.path.dirname(path)):
90+
with in_directory(os.path.dirname(manifest.path)):
9091
exceptions: List[str] = []
9192
for project in manifest.selected_projects(args.projects):
9293
with catch_runtime_exceptions(exceptions) as exceptions:
9394
dfetch.project.make(project).check_for_update(reporters)
9495

9596
if not args.no_recommendations and os.path.isdir(project.destination):
9697
with in_directory(project.destination):
97-
check_child_manifests(manifest, project, path)
98+
check_child_manifests(manifest, project)
9899

99100
for reporter in reporters:
100101
reporter.dump_to_file()
@@ -103,21 +104,23 @@ def __call__(self, args: argparse.Namespace) -> None:
103104
raise RuntimeError("\n".join(exceptions))
104105

105106
@staticmethod
106-
def _get_reporters(args: argparse.Namespace, path: str) -> List[CheckReporter]:
107+
def _get_reporters(
108+
args: argparse.Namespace, manifest: Manifest
109+
) -> List[CheckReporter]:
107110
"""Get all reporters.
108111
109112
Args:
110113
args (argparse.Namespace): Arguments given to the command line
111-
path (str): Path to the manifest
114+
manifest (Manifest): The manifest
112115
113116
Returns:
114117
List[CheckReporter]: List of reporters that each provide a unique report
115118
"""
116-
reporters: List[CheckReporter] = [CheckStdoutReporter(path)]
119+
reporters: List[CheckReporter] = [CheckStdoutReporter(manifest)]
117120
if args.jenkins_json:
118-
reporters += [JenkinsReporter(path, args.jenkins_json)]
121+
reporters += [JenkinsReporter(manifest, args.jenkins_json)]
119122
if args.sarif:
120-
reporters += [SarifReporter(path, args.sarif)]
123+
reporters += [SarifReporter(manifest, args.sarif)]
121124
if args.code_climate:
122-
reporters += [CodeClimateReporter(path, args.code_climate)]
125+
reporters += [CodeClimateReporter(manifest, args.code_climate)]
123126
return reporters

dfetch/commands/common.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,14 @@
1212
logger = get_logger(__name__)
1313

1414

15-
def check_child_manifests(manifest: Manifest, project: ProjectEntry, path: str) -> None:
15+
def check_child_manifests(manifest: Manifest, project: ProjectEntry) -> None:
1616
"""Check for child manifests within a project.
1717
1818
Args:
1919
manifest (dfetch.manifest.manifest.Manifest): The parent manifest with projects.
2020
project (ProjectEntry): The parent project.
21-
path (str): The path of the parent manifest.
2221
"""
23-
for (
24-
childmanifest,
25-
childmanifest_path,
26-
) in get_childmanifests(skip=[path]):
22+
for childmanifest in get_childmanifests(skip=[manifest.path]):
2723
recommendations: List[ProjectEntry] = []
2824
for childproject in childmanifest.projects:
2925
if childproject.remote_url not in [
@@ -32,10 +28,10 @@ def check_child_manifests(manifest: Manifest, project: ProjectEntry, path: str)
3228
recommendations.append(childproject.as_recommendation())
3329

3430
if recommendations:
35-
childmanifest_path = os.path.relpath(
36-
childmanifest_path, start=os.path.dirname(path)
31+
childmanifest_relpath = os.path.relpath(
32+
childmanifest.path, start=os.path.dirname(manifest.path)
3733
).replace("\\", "/")
38-
_make_recommendation(project, recommendations, childmanifest_path)
34+
_make_recommendation(project, recommendations, childmanifest_relpath)
3935

4036

4137
def _make_recommendation(

dfetch/commands/diff.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,10 @@ def create_menu(subparsers: dfetch.commands.command.SubparserActionType) -> None
100100

101101
def __call__(self, args: argparse.Namespace) -> None:
102102
"""Perform the diff."""
103-
manifest, path = dfetch.manifest.manifest.get_manifest()
103+
manifest = dfetch.manifest.manifest.get_manifest()
104104
revs = [r for r in args.revs.strip(":").split(":", maxsplit=1) if r]
105105

106-
with in_directory(os.path.dirname(path)):
106+
with in_directory(os.path.dirname(manifest.path)):
107107
exceptions: List[str] = []
108108
projects = manifest.selected_projects(args.projects)
109109
if not projects:
@@ -113,10 +113,10 @@ def __call__(self, args: argparse.Namespace) -> None:
113113
for project in projects:
114114
patch_name = f"{project.name}.patch"
115115
with catch_runtime_exceptions(exceptions) as exceptions:
116-
repo = _get_repo(path, project)
116+
repo = _get_repo(manifest.path, project)
117117
patch = _diff_from_repo(repo, project, revs)
118118

119-
_dump_patch(path, revs, project, patch_name, patch)
119+
_dump_patch(manifest.path, revs, project, patch_name, patch)
120120

121121
if exceptions:
122122
raise RuntimeError("\n".join(exceptions))

dfetch/commands/freeze.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,12 @@ def __call__(self, args: argparse.Namespace) -> None:
7070
"""Perform the freeze."""
7171
del args # unused
7272

73-
manifest, path = get_manifest()
73+
manifest = get_manifest()
7474

7575
exceptions: List[str] = []
7676
projects: List[ProjectEntry] = []
7777

78-
with in_directory(os.path.dirname(path)):
78+
with in_directory(os.path.dirname(manifest.path)):
7979
for project in manifest.projects:
8080
with catch_runtime_exceptions(exceptions) as exceptions:
8181
on_disk_version = dfetch.project.make(project).on_disk_version()

dfetch/commands/report.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ def create_menu(subparsers: dfetch.commands.command.SubparserActionType) -> None
6363

6464
def __call__(self, args: argparse.Namespace) -> None:
6565
"""Generate the report."""
66-
manifest, path = dfetch.manifest.manifest.get_manifest()
66+
manifest = dfetch.manifest.manifest.get_manifest()
6767

68-
with dfetch.util.util.in_directory(os.path.dirname(path)):
69-
reporter = REPORTERS[args.type](path)
68+
with dfetch.util.util.in_directory(os.path.dirname(manifest.path)):
69+
reporter = REPORTERS[args.type](manifest)
7070

7171
for project in manifest.selected_projects(args.projects):
7272
determined_licenses = self._determine_licenses(project)

dfetch/commands/update.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ def create_menu(subparsers: dfetch.commands.command.SubparserActionType) -> None
6969

7070
def __call__(self, args: argparse.Namespace) -> None:
7171
"""Perform the update."""
72-
manifest, path = dfetch.manifest.manifest.get_manifest()
72+
manifest = dfetch.manifest.manifest.get_manifest()
7373

7474
exceptions: List[str] = []
7575
destinations: List[str] = [
7676
os.path.realpath(project.destination) for project in manifest.projects
7777
]
78-
with in_directory(os.path.dirname(path)):
78+
with in_directory(os.path.dirname(manifest.path)):
7979
for project in manifest.selected_projects(args.projects):
8080
with catch_runtime_exceptions(exceptions) as exceptions:
8181
self._check_destination(project, destinations)
@@ -85,7 +85,7 @@ def __call__(self, args: argparse.Namespace) -> None:
8585
project.destination
8686
):
8787
with in_directory(project.destination):
88-
check_child_manifests(manifest, project, path)
88+
check_child_manifests(manifest, project)
8989

9090
if exceptions:
9191
raise RuntimeError("\n".join(exceptions))

dfetch/manifest/manifest.py

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io
2323
import os
2424
import pathlib
25+
import re
2526
from typing import IO, Any, Dict, List, Optional, Sequence, Tuple, Union
2627

2728
import yaml
@@ -102,9 +103,16 @@ class Manifest:
102103

103104
CURRENT_VERSION = "0.0"
104105

105-
def __init__(self, manifest: ManifestDict) -> None:
106+
def __init__(
107+
self,
108+
manifest: ManifestDict,
109+
text: Optional[str] = None,
110+
path: Optional[Union[str, os.PathLike[str]]] = None,
111+
) -> None:
106112
"""Create the manifest."""
107113
self.__version: str = str(manifest.get("version", self.CURRENT_VERSION))
114+
self.__text: str = str(text)
115+
self.__path: str = str(path)
108116

109117
self._remotes, default_remotes = self._determine_remotes(
110118
manifest.get("remotes", [])
@@ -180,7 +188,10 @@ def _determine_remotes(
180188
return (remotes, default_remotes)
181189

182190
@staticmethod
183-
def from_yaml(text: Union[io.TextIOWrapper, str, IO[str]]) -> "Manifest":
191+
def from_yaml(
192+
text: Union[io.TextIOWrapper, str, IO[str]],
193+
path: Optional[Union[str, os.PathLike[str]]] = None,
194+
) -> "Manifest":
184195
"""Create a manifest from a file like object."""
185196
loaded_yaml = Manifest._load_yaml(text)
186197

@@ -192,7 +203,11 @@ def from_yaml(text: Union[io.TextIOWrapper, str, IO[str]]) -> "Manifest":
192203
if not manifest:
193204
raise RuntimeError("Missing manifest root element!")
194205

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

197212
@staticmethod
198213
def _load_yaml(text: Union[io.TextIOWrapper, str, IO[str]]) -> Any:
@@ -217,7 +232,12 @@ def from_file(path: str) -> "Manifest":
217232
FileNotFoundError: Given path was not a file.
218233
"""
219234
with open(path, "r", encoding="utf-8") as opened_file:
220-
return Manifest.from_yaml(opened_file)
235+
return Manifest.from_yaml(opened_file, path)
236+
237+
@property
238+
def path(self) -> str:
239+
"""Path to the manifest file."""
240+
return self.__path
221241

222242
@property
223243
def version(self) -> str:
@@ -293,6 +313,25 @@ def dump(self, path: str) -> None:
293313
self._as_dict(), manifest_file, Dumper=ManifestDumper, sort_keys=False
294314
)
295315

316+
def find_name_in_manifest(self, name: str) -> Tuple[int, int, int]:
317+
"""Find the location of a project name in the manifest."""
318+
if not self.__text:
319+
raise FileNotFoundError("No manifest text available")
320+
321+
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)
323+
324+
if match:
325+
return (
326+
line_nr,
327+
int(match.start("name")) + 1,
328+
int(match.end("name")),
329+
)
330+
raise RuntimeError(
331+
"An entry from the manifest was provided,"
332+
" that doesn't exist in the manifest!"
333+
)
334+
296335

297336
def find_manifest() -> str:
298337
"""Find a manifest."""
@@ -308,25 +347,22 @@ def find_manifest() -> str:
308347
return os.path.realpath(paths[0])
309348

310349

311-
def get_manifest() -> Tuple[Manifest, str]:
350+
def get_manifest() -> Manifest:
312351
"""Get manifest and its path."""
313352
logger.debug("Looking for manifest")
314353
manifest_path = find_manifest()
315354
validate(manifest_path)
316355

317356
logger.debug(f"Using manifest {manifest_path}")
318-
return (
319-
Manifest.from_file(manifest_path),
320-
manifest_path,
321-
)
357+
return Manifest.from_file(manifest_path)
322358

323359

324-
def get_childmanifests(skip: Optional[List[str]] = None) -> List[Tuple[Manifest, str]]:
360+
def get_childmanifests(skip: Optional[List[str]] = None) -> List[Manifest]:
325361
"""Get manifest and its path."""
326362
skip = skip or []
327363
logger.debug("Looking for sub-manifests")
328364

329-
childmanifests: List[Tuple[Manifest, str]] = []
365+
childmanifests: List[Manifest] = []
330366
for path in find_file(DEFAULT_MANIFEST_NAME, "."):
331367
path = os.path.realpath(path)
332368
if path not in skip:
@@ -335,8 +371,7 @@ def get_childmanifests(skip: Optional[List[str]] = None) -> List[Tuple[Manifest,
335371
pathlib.Path(path).relative_to(os.path.dirname(os.getcwd())).as_posix()
336372
):
337373
validate(path)
338-
childmanifest = Manifest.from_file(path)
339-
childmanifests += [(childmanifest, path)]
374+
childmanifests += [Manifest.from_file(path)]
340375

341376
return childmanifests
342377

dfetch/reporting/check/code_climate_reporter.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
from typing import Any, Dict, List
6262

6363
from dfetch.log import get_logger
64+
from dfetch.manifest.manifest import Manifest
6465
from dfetch.manifest.project import ProjectEntry
6566
from dfetch.reporting.check.reporter import CheckReporter, Issue, IssueSeverity
6667

@@ -82,14 +83,14 @@ class CodeClimateReporter(CheckReporter):
8283

8384
name = "code-climate"
8485

85-
def __init__(self, manifest_path: str, report_path: str) -> None:
86+
def __init__(self, manifest: Manifest, report_path: str) -> None:
8687
"""Create the code climate reporter.
8788
8889
Args:
89-
manifest_path (str): Path to the manifest.
90+
manifest (Manifest): The manifest.
9091
report_path (str): Output path of the report.
9192
"""
92-
super().__init__(manifest_path)
93+
super().__init__(manifest)
9394

9495
self._report_path = report_path
9596

@@ -111,7 +112,7 @@ def add_issue(self, project: ProjectEntry, issue: Issue) -> None:
111112
project (ProjectEntry): Project with the issue
112113
issue (Issue): The issue to add to the report
113114
"""
114-
line, col_start, col_end = self.find_name_in_manifest(project.name)
115+
line, col_start, col_end = self._manifest.find_name_in_manifest(project.name)
115116

116117
self._report += [
117118
{
@@ -123,7 +124,7 @@ def add_issue(self, project: ProjectEntry, issue: Issue) -> None:
123124
).hexdigest(),
124125
"severity": self._determine_severity(issue.severity).value,
125126
"location": {
126-
"path": os.path.relpath(self._manifest_path),
127+
"path": os.path.relpath(self._manifest.path),
127128
"positions": {
128129
"begin": {"line": line, "column": col_start},
129130
"end": {"line": line, "column": col_end},

dfetch/reporting/check/jenkins_reporter.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
from typing import Any, Dict
5656

5757
from dfetch.log import get_logger
58+
from dfetch.manifest.manifest import Manifest
5859
from dfetch.manifest.project import ProjectEntry
5960
from dfetch.reporting.check.reporter import CheckReporter, Issue
6061

@@ -66,14 +67,14 @@ class JenkinsReporter(CheckReporter):
6667

6768
name = "jenkins"
6869

69-
def __init__(self, manifest_path: str, report_path: str) -> None:
70+
def __init__(self, manifest: Manifest, report_path: str) -> None:
7071
"""Create the jenkins reporter.
7172
7273
Args:
73-
manifest_path (str): Path to the manifest.
74+
manifest (Manifest): The manifest.
7475
report_path (str): Output path of the report.
7576
"""
76-
super().__init__(manifest_path)
77+
super().__init__(manifest)
7778

7879
self._report_path = report_path
7980

@@ -89,10 +90,10 @@ def add_issue(self, project: ProjectEntry, issue: Issue) -> None:
8990
project (ProjectEntry): Project with the issue
9091
issue (Issue): The issue to add to the report
9192
"""
92-
line, col_start, col_end = self.find_name_in_manifest(project.name)
93+
line, col_start, col_end = self._manifest.find_name_in_manifest(project.name)
9394
self._report["issues"] += [
9495
{
95-
"fileName": os.path.relpath(self._manifest_path),
96+
"fileName": os.path.relpath(self._manifest.path),
9697
"severity": str(issue.severity.value),
9798
"message": f"{project.name} : {issue.message}",
9899
"description": issue.description,

0 commit comments

Comments
 (0)