2121"""
2222
2323
24- class CargoTomlHandler (models .DatafileHandler ):
25- datasource_id = 'cargo_toml'
26- path_patterns = ('*/Cargo.toml' , '*/cargo.toml' ,)
27- default_package_type = 'cargo'
28- default_primary_language = 'Rust'
29- description = 'Rust Cargo.toml package manifest'
30- documentation_url = 'https://doc.rust-lang.org/cargo/reference/manifest.html'
31-
32- @classmethod
33- def parse (cls , location ):
34- package_data = toml .load (location , _dict = dict )
35- core_package_data = package_data .get ('package' , {})
36- workspace = package_data .get ('workspace' , {})
37-
38- name = core_package_data .get ('name' )
39- version = core_package_data .get ('version' )
40- description = core_package_data .get ('description' ) or ''
41- description = description .strip ()
42-
43- authors = core_package_data .get ('authors' ) or []
44- parties = list (get_parties (person_names = authors , party_role = 'author' ))
45-
46- extracted_license_statement = core_package_data .get ('license' )
47- # TODO: load as a notice_text
48- license_file = core_package_data .get ('license-file' )
49-
50- keywords = core_package_data .get ('keywords' ) or []
51- categories = core_package_data .get ('categories' ) or []
52- keywords .extend (categories )
53-
54- # cargo dependencies are complex and can be overriden at multiple levels
55- dependencies = []
56- for key , value in core_package_data .items ():
57- if key .endswith ('dependencies' ):
58- dependencies .extend (dependency_mapper (dependencies = value , scope = key ))
59-
60- # TODO: add file refs:
61- # - readme, include and exclude
62- # TODO: other URLs
63- # - documentation
64-
65- vcs_url = core_package_data .get ('repository' )
66- homepage_url = core_package_data .get ('homepage' )
67- repository_homepage_url = name and f'https://crates.io/crates/{ name } '
68- repository_download_url = name and version and f'https://crates.io/api/v1/crates/{ name } /{ version } /download'
69- api_data_url = name and f'https://crates.io/api/v1/crates/{ name } '
70- extra_data = {}
71- if workspace :
72- extra_data ["workspace" ] = workspace
73-
74- yield models .PackageData (
75- datasource_id = cls .datasource_id ,
76- type = cls .default_package_type ,
77- name = name ,
78- version = version ,
79- primary_language = cls .default_primary_language ,
80- description = description ,
81- parties = parties ,
82- extracted_license_statement = extracted_license_statement ,
83- vcs_url = vcs_url ,
84- homepage_url = homepage_url ,
85- repository_homepage_url = repository_homepage_url ,
86- repository_download_url = repository_download_url ,
87- api_data_url = api_data_url ,
88- dependencies = dependencies ,
89- extra_data = extra_data ,
90- )
91-
24+ class CargoBaseHandler (models .DatafileHandler ):
9225 @classmethod
9326 def assemble (cls , package_data , resource , codebase , package_adder ):
9427 """
@@ -161,6 +94,79 @@ def update_resource_package_data(cls, package_data, old_package_data, mapping=No
16194 return old_package_data
16295
16396
97+
98+ class CargoTomlHandler (CargoBaseHandler ):
99+ datasource_id = 'cargo_toml'
100+ path_patterns = ('*/Cargo.toml' , '*/cargo.toml' ,)
101+ default_package_type = 'cargo'
102+ default_primary_language = 'Rust'
103+ description = 'Rust Cargo.toml package manifest'
104+ documentation_url = 'https://doc.rust-lang.org/cargo/reference/manifest.html'
105+
106+ @classmethod
107+ def parse (cls , location ):
108+ package_data = toml .load (location , _dict = dict )
109+ core_package_data = package_data .get ('package' , {})
110+ workspace = package_data .get ('workspace' , {})
111+
112+ name = core_package_data .get ('name' )
113+ version = core_package_data .get ('version' )
114+ if isinstance (version , dict ) and "workspace" in version :
115+ version = "workspace"
116+
117+ description = core_package_data .get ('description' ) or ''
118+ description = description .strip ()
119+
120+ authors = core_package_data .get ('authors' ) or []
121+ parties = list (get_parties (person_names = authors , party_role = 'author' ))
122+
123+ extracted_license_statement = core_package_data .get ('license' )
124+ # TODO: load as a notice_text
125+ license_file = core_package_data .get ('license-file' )
126+
127+ keywords = core_package_data .get ('keywords' ) or []
128+ categories = core_package_data .get ('categories' ) or []
129+ keywords .extend (categories )
130+
131+ # cargo dependencies are complex and can be overriden at multiple levels
132+ dependencies = []
133+ for key , value in core_package_data .items ():
134+ if key .endswith ('dependencies' ):
135+ dependencies .extend (dependency_mapper (dependencies = value , scope = key ))
136+
137+ # TODO: add file refs:
138+ # - readme, include and exclude
139+ # TODO: other URLs
140+ # - documentation
141+
142+ vcs_url = core_package_data .get ('repository' )
143+ homepage_url = core_package_data .get ('homepage' )
144+ repository_homepage_url = name and f'https://crates.io/crates/{ name } '
145+ repository_download_url = name and version and f'https://crates.io/api/v1/crates/{ name } /{ version } /download'
146+ api_data_url = name and f'https://crates.io/api/v1/crates/{ name } '
147+ extra_data = {}
148+ if workspace :
149+ extra_data ["workspace" ] = workspace
150+
151+ yield models .PackageData (
152+ datasource_id = cls .datasource_id ,
153+ type = cls .default_package_type ,
154+ name = name ,
155+ version = version ,
156+ primary_language = cls .default_primary_language ,
157+ description = description ,
158+ parties = parties ,
159+ extracted_license_statement = extracted_license_statement ,
160+ vcs_url = vcs_url ,
161+ homepage_url = homepage_url ,
162+ repository_homepage_url = repository_homepage_url ,
163+ repository_download_url = repository_download_url ,
164+ api_data_url = api_data_url ,
165+ dependencies = dependencies ,
166+ extra_data = extra_data ,
167+ )
168+
169+
164170CARGO_ATTRIBUTE_MAPPING = {
165171 # Fields in PackageData model: Fields in cargo
166172 "homepage_url" : "homepage" ,
@@ -173,7 +179,7 @@ def update_resource_package_data(cls, package_data, old_package_data, mapping=No
173179 "declared_license_expression_spdx" : "declared_license_expression_spdx" ,
174180}
175181
176- class CargoLockHandler (models . DatafileHandler ):
182+ class CargoLockHandler (CargoBaseHandler ):
177183 datasource_id = 'cargo_lock'
178184 path_patterns = ('*/Cargo.lock' , '*/cargo.lock' ,)
179185 default_package_type = 'cargo'
@@ -220,18 +226,6 @@ def parse(cls, location):
220226 dependencies = dependencies ,
221227 )
222228
223- @classmethod
224- def assemble (cls , package_data , resource , codebase , package_adder ):
225- """
226- Assemble Cargo.toml and possible Cargo.lock datafiles
227- """
228- yield from cls .assemble_from_many_datafiles (
229- datafile_name_patterns = ('Cargo.toml' , 'Cargo.lock' ,),
230- directory = resource .parent (codebase ),
231- codebase = codebase ,
232- package_adder = package_adder ,
233- )
234-
235229
236230def dependency_mapper (dependencies , scope = 'dependencies' ):
237231 """
@@ -261,13 +255,11 @@ def dependency_mapper(dependencies, scope='dependencies'):
261255 )
262256
263257
264- def get_parties (person_names , party_role , debug = False ):
258+ def get_parties (person_names , party_role ):
265259 """
266260 Yields Party of `party_role` given a list of ``person_names`` strings.
267261 https://doc.rust-lang.org/cargo/reference/manifest.html#the-authors-field-optional
268262 """
269- if debug :
270- raise Exception (person_names )
271263 for person_name in person_names :
272264 name , email = parse_person (person_name )
273265 yield models .Party (
0 commit comments