6
6
from copy import deepcopy
7
7
from dataclasses import field
8
8
from enum import Enum , auto
9
- from typing import Literal
9
+ from typing import Literal , cast
10
10
11
+ from pydantic import BaseModel , ConfigDict , model_serializer
11
12
from pydantic .dataclasses import dataclass
12
13
13
- OpossumPackageIdentifier = str
14
- ResourcePath = str
14
+ type OpossumPackageIdentifier = str
15
+ type ResourcePath = str
16
+ type ResourceInFile = dict [str , ResourceInFile ] | int
15
17
16
18
17
19
@dataclass (frozen = True )
18
20
class OpossumInformation :
19
21
metadata : Metadata
20
- resources : Resource
22
+ resources : ResourceInFile
21
23
externalAttributions : dict [OpossumPackageIdentifier , OpossumPackage ]
22
24
resourcesToAttributions : dict [ResourcePath , list [OpossumPackageIdentifier ]]
23
25
attributionBreakpoints : list [str ] = field (default_factory = list )
24
26
externalAttributionSources : dict [str , ExternalAttributionSource ] = field (
25
27
default_factory = dict
26
28
)
29
+ frequentLicenses : list [FrequentLicense ] | None = None
30
+ filesWithChildren : list [str ] | None = None
31
+ baseUrlsForSources : BaseUrlsForSources | None = None
32
+
33
+
34
+ class BaseUrlsForSources (BaseModel ):
35
+ @model_serializer
36
+ def serialize (self ) -> dict :
37
+ # hack to override not serializing keys with corresponding value none:
38
+ # In this case this is valid and should be part of the serialization
39
+ return {k : v for k , v in self }
40
+
41
+ model_config = ConfigDict (extra = "allow" , frozen = True )
42
+
43
+
44
+ class FrequentLicense (BaseModel ):
45
+ fullName : str
46
+ shortName : str
47
+ defaultText : str
27
48
28
49
29
50
@dataclass (frozen = True )
30
51
class SourceInfo :
31
52
name : str
32
- documentConfidence : int | None = 0
53
+ documentConfidence : int | float | None = 0
54
+ additionalName : str | None = None
33
55
34
56
35
57
@dataclass (frozen = True )
@@ -51,11 +73,13 @@ class OpossumPackage:
51
73
preSelected : bool | None = None
52
74
followUp : Literal ["FOLLOW_UP" ] | None = None
53
75
originId : str | None = None
76
+ originIds : list [str ] | None = None
54
77
criticality : Literal ["high" ] | Literal ["medium" ] | None = None
78
+ wasPreferred : bool | None = None
55
79
56
80
57
- @ dataclass ( frozen = True )
58
- class Metadata :
81
+ class Metadata ( BaseModel ):
82
+ model_config = ConfigDict ( extra = "allow" , frozen = True )
59
83
projectId : str
60
84
fileCreationDate : str
61
85
projectTitle : str
@@ -123,7 +147,7 @@ def drop_element(
123
147
124
148
return resource
125
149
126
- def to_dict (self ) -> int | dict :
150
+ def to_dict (self ) -> ResourceInFile :
127
151
if not self .has_children ():
128
152
if self .type == ResourceType .FOLDER :
129
153
return {}
@@ -154,8 +178,33 @@ def get_paths_of_all_leaf_nodes_with_types(
154
178
def has_children (self ) -> bool :
155
179
return len (self .children ) > 0
156
180
181
+ def convert_to_file_resource (self ) -> ResourceInFile :
182
+ return self .to_dict ()
183
+
157
184
158
185
@dataclass (frozen = True )
159
186
class ExternalAttributionSource :
160
187
name : str
161
188
priority : int
189
+ isRelevantForPreferred : bool | None = None
190
+
191
+
192
+ def _build_resource_tree (resource : ResourceInFile ) -> Resource :
193
+ if isinstance (resource , int ):
194
+ return Resource (type = ResourceType .FILE )
195
+ else :
196
+ result = Resource (type = ResourceType .FOLDER )
197
+ for name , child_resource in resource .items ():
198
+ result .children [name ] = _build_resource_tree (child_resource )
199
+ return result
200
+
201
+
202
+ def convert_resource_in_file_to_resource (resource : ResourceInFile ) -> Resource :
203
+ root_node = Resource (ResourceType .TOP_LEVEL )
204
+
205
+ if isinstance (resource , dict ):
206
+ dict_resource = cast (dict [str , ResourceInFile ], resource )
207
+ for name , child_resource in dict_resource .items ():
208
+ root_node .children [name ] = _build_resource_tree (child_resource )
209
+
210
+ return root_node
0 commit comments