Skip to content

Commit e71ec1c

Browse files
committed
Refactor the ort module to match the Kotlin classes
Signed-off-by: tdruez <[email protected]>
1 parent a14261a commit e71ec1c

File tree

1 file changed

+66
-51
lines changed

1 file changed

+66
-51
lines changed

scanpipe/pipes/ort.py

Lines changed: 66 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -28,95 +28,110 @@
2828

2929
import saneyaml
3030

31+
"""
32+
This module provides Python dataclass models for representing a package list
33+
in a format compatible with the OSS Review Toolkit (ORT)
34+
`CreateAnalyzerResultFromPackageListCommand`.
3135
36+
The models are simplified adaptations of the Kotlin classes from:
37+
https://github.com/oss-review-toolkit/ort/blob/main/cli-helper/src/main/kotlin/commands/CreateAnalyzerResultFromPackageListCommand.kt
38+
39+
This module is intended for generating ORT-compatible YAML package lists from Python
40+
objects, allowing integration with ORT's analyzer workflows or manual creation of
41+
package metadata.
42+
"""
43+
44+
45+
# private data class SourceArtifact(
46+
# val url: String,
47+
# val hash: Hash? = null
48+
# )
3249
@dataclass
3350
class SourceArtifact:
3451
url: str
52+
hash: str = None
3553

3654

55+
# private data class Vcs(
56+
# val type: String? = null,
57+
# val url: String? = null,
58+
# val revision: String? = null,
59+
# val path: String? = null
60+
# )
3761
@dataclass
38-
class VCS:
39-
type: str = ""
40-
url: str = ""
41-
revision: str = ""
42-
path: str = ""
43-
sourceArtifact: SourceArtifact | None = None
44-
45-
62+
class Vcs:
63+
type: str = None
64+
url: str = None
65+
revision: str = None
66+
path: str = None
67+
68+
69+
# private data class Dependency(
70+
# val id: Identifier,
71+
# val purl: String? = null,
72+
# val vcs: Vcs? = null,
73+
# val sourceArtifact: SourceArtifact? = null,
74+
# val declaredLicenses: Set<String> = emptySet(),
75+
# val concludedLicense: SpdxExpression? = null,
76+
# val isExcluded: Boolean = false,
77+
# val isDynamicallyLinked: Boolean = false,
78+
# val labels: Map<String, String> = emptyMap()
79+
# )
4680
@dataclass
4781
class Dependency:
4882
id: str
49-
purl: str
50-
sourceArtifact: SourceArtifact
51-
vcs: VCS = field(default_factory=VCS)
52-
declaredLicenses: list[str] = field(default_factory=list)
83+
purl: str = None
84+
vcs: Vcs = None
85+
sourceArtifact: SourceArtifact = None
86+
declaredLicenses: list = field(default_factory=set)
87+
# concludedLicense: str = None
88+
# isExcluded: bool = False
89+
# isDynamicallyLinked: bool = False
90+
# labels: dict = field(default_factory=dict)
91+
92+
# Additions to the initial model:
5393
description: str = ""
5494
homepageUrl: str = ""
5595

5696

97+
# private data class PackageList(
98+
# val projectName: String? = null,
99+
# val projectVcs: Vcs? = null,
100+
# val dependencies: List<Dependency> = emptyList()
101+
# )
57102
@dataclass
58-
class Project:
103+
class PackageList:
59104
projectName: str
60-
projectVcs: VCS = field(default_factory=VCS)
61-
dependencies: list[Dependency] = field(default_factory=list)
62-
63-
@classmethod
64-
def from_yaml(cls, yaml_str: str):
65-
"""Create a Project object from a YAML string."""
66-
data = saneyaml.load(yaml_str)
67-
68-
# Parse dependencies
69-
dependencies = [
70-
Dependency(
71-
id=dependency["id"],
72-
purl=dependency["purl"],
73-
sourceArtifact=SourceArtifact(**dependency["sourceArtifact"]),
74-
declaredLicenses=dependency.get("declaredLicenses", []),
75-
)
76-
for dependency in data.get("dependencies", [])
77-
]
78-
79-
# Optional projectVcs
80-
vcs_data = data.get("projectVcs", {})
81-
project_vcs = VCS(**vcs_data) if vcs_data else VCS()
82-
83-
return cls(
84-
projectName=data["projectName"],
85-
dependencies=dependencies,
86-
projectVcs=project_vcs,
87-
)
88-
89-
@classmethod
90-
def from_file(cls, filepath: str | Path):
91-
"""Create a Project object by loading a YAML file."""
92-
return cls.from_yaml(Path(filepath).read_text(encoding="utf-8"))
105+
projectVcs: Vcs = None
106+
dependencies: list = field(default_factory=list)
93107

94-
def to_yaml(self) -> str:
108+
def to_yaml(self):
95109
"""Dump the Project object back to a YAML string."""
96110
return saneyaml.dump(asdict(self))
97111

98-
def to_file(self, filepath: str | Path):
112+
def to_file(self, filepath):
99113
"""Write the Project object to a YAML file."""
100114
Path(filepath).write_text(self.to_yaml(), encoding="utf-8")
101115

102116

103117
def to_ort_package_list_yml(project):
118+
"""Convert a project object into a YAML string in the ORT package list format."""
104119
dependencies = []
105120
for package in project.discoveredpackages.all():
106121
dependency = Dependency(
107122
id=f"{package.type}::{package.name}:{package.version}",
108123
purl=package.purl,
109124
sourceArtifact=SourceArtifact(url=package.download_url),
110125
declaredLicenses=[package.get_declared_license_expression_spdx()],
111-
vcs=VCS(url=package.vcs_url),
126+
vcs=Vcs(url=package.vcs_url),
112127
description=package.description,
113128
homepageUrl=package.homepage_url,
114129
)
115130
dependencies.append(dependency)
116131

117-
project = Project(
132+
package_list = PackageList(
118133
projectName=project.name,
119134
dependencies=dependencies,
120135
)
121136

122-
return project.to_yaml()
137+
return package_list.to_yaml()

0 commit comments

Comments
 (0)