|
28 | 28 |
|
29 | 29 | import saneyaml |
30 | 30 |
|
| 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`. |
31 | 35 |
|
| 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 | +# ) |
32 | 49 | @dataclass |
33 | 50 | class SourceArtifact: |
34 | 51 | url: str |
| 52 | + hash: str = None |
35 | 53 |
|
36 | 54 |
|
| 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 | +# ) |
37 | 61 | @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 | +# ) |
46 | 80 | @dataclass |
47 | 81 | class Dependency: |
48 | 82 | 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: |
53 | 93 | description: str = "" |
54 | 94 | homepageUrl: str = "" |
55 | 95 |
|
56 | 96 |
|
| 97 | +# private data class PackageList( |
| 98 | +# val projectName: String? = null, |
| 99 | +# val projectVcs: Vcs? = null, |
| 100 | +# val dependencies: List<Dependency> = emptyList() |
| 101 | +# ) |
57 | 102 | @dataclass |
58 | | -class Project: |
| 103 | +class PackageList: |
59 | 104 | 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) |
93 | 107 |
|
94 | | - def to_yaml(self) -> str: |
| 108 | + def to_yaml(self): |
95 | 109 | """Dump the Project object back to a YAML string.""" |
96 | 110 | return saneyaml.dump(asdict(self)) |
97 | 111 |
|
98 | | - def to_file(self, filepath: str | Path): |
| 112 | + def to_file(self, filepath): |
99 | 113 | """Write the Project object to a YAML file.""" |
100 | 114 | Path(filepath).write_text(self.to_yaml(), encoding="utf-8") |
101 | 115 |
|
102 | 116 |
|
103 | 117 | def to_ort_package_list_yml(project): |
| 118 | + """Convert a project object into a YAML string in the ORT package list format.""" |
104 | 119 | dependencies = [] |
105 | 120 | for package in project.discoveredpackages.all(): |
106 | 121 | dependency = Dependency( |
107 | 122 | id=f"{package.type}::{package.name}:{package.version}", |
108 | 123 | purl=package.purl, |
109 | 124 | sourceArtifact=SourceArtifact(url=package.download_url), |
110 | 125 | declaredLicenses=[package.get_declared_license_expression_spdx()], |
111 | | - vcs=VCS(url=package.vcs_url), |
| 126 | + vcs=Vcs(url=package.vcs_url), |
112 | 127 | description=package.description, |
113 | 128 | homepageUrl=package.homepage_url, |
114 | 129 | ) |
115 | 130 | dependencies.append(dependency) |
116 | 131 |
|
117 | | - project = Project( |
| 132 | + package_list = PackageList( |
118 | 133 | projectName=project.name, |
119 | 134 | dependencies=dependencies, |
120 | 135 | ) |
121 | 136 |
|
122 | | - return project.to_yaml() |
| 137 | + return package_list.to_yaml() |
0 commit comments