88#
99
1010import xmltodict
11+ from packageurl import PackageURL
1112
1213from packagedcode import models
1314from packagedcode .utils import build_description
1415
1516"""
1617Handle NuGet packages and their manifests.
1718"""
18- # TODO: add dependencies
19+
20+
21+ def get_dependencies (nuspec ):
22+ """
23+ Yield DependentPackage found in a NuGet ``nuspec`` object.
24+ """
25+ # This is either a list of dependency or a list of group/dependency
26+ # or a single dep or a single group mapping
27+
28+ dependencies = nuspec .get ('dependencies' ) or []
29+ if isinstance (dependencies , dict ):
30+ # wrap the mapping in a list if we have more than one dependencies
31+ dependencies = [dependencies ]
32+
33+ for depends in dependencies :
34+ groups = depends .get ('group' ) or []
35+ if groups :
36+ if isinstance (groups , dict ):
37+ # wrap the mapping in a list
38+ groups = [groups ]
39+
40+ for group in groups :
41+ extra_data = dict (framework = group ['@targetFramework' ])
42+ deps = group .get ('dependency' ) or []
43+ yield from _get_dep_packs (deps , extra_data )
44+ else :
45+ # {'dependency': {'@id': 'jQuery', '@version': '1.9.1'}}
46+ deps = depends .get ('dependency' ) or []
47+ yield from _get_dep_packs (deps , extra_data = {})
48+
49+
50+ def _get_dep_packs (deps , extra_data ):
51+ """
52+ Yield DependentPackage found in a NuGet ``deps`` mapping or list of mappings.
53+ """
54+ if not deps :
55+ return
56+
57+ if isinstance (deps , dict ):
58+ # wrap the mapping in a list
59+ deps = [deps ]
60+
61+ for dep in deps :
62+ extra = dict (extra_data ) or {}
63+ include = dep .get ('@include' )
64+ if include :
65+ extra ['include' ] = include
66+ exclude = dep .get ('@exclude' )
67+ if exclude :
68+ extra ['exclude' ] = exclude
69+
70+ yield models .DependentPackage (
71+ purl = str (PackageURL (type = 'nuget' , name = dep .get ('@id' ))),
72+ # this is a range, not a version
73+ extracted_requirement = dep .get ('@version' ),
74+ scope = 'dependency' ,
75+ is_runtime = True ,
76+ is_optional = False ,
77+ is_resolved = False ,
78+ extra_data = extra ,
79+ )
1980
2081
2182def get_urls (name , version , ** kwargs ):
@@ -46,7 +107,7 @@ class NugetNuspecHandler(models.DatafileHandler):
46107
47108 @classmethod
48109 def parse (cls , location ):
49- with open (location , 'rb' ) as loc :
110+ with open (location , 'rb' ) as loc :
50111 parsed = xmltodict .parse (loc )
51112
52113 if not parsed :
@@ -62,14 +123,14 @@ def parse(cls, location):
62123
63124 # Summary: A short description of the package for UI display. If omitted, a
64125 # truncated version of description is used.
65- description = build_description (nuspec .get ('summary' ) , nuspec .get ('description' ))
126+ description = build_description (nuspec .get ('summary' ), nuspec .get ('description' ))
66127
67128 # title: A human-friendly title of the package, typically used in UI
68129 # displays as on nuget.org and the Package Manager in Visual Studio. If not
69130 # specified, the package ID is used.
70131 title = nuspec .get ('title' )
71132 if title and title != name :
72- description = build_description (nuspec . get ( ' title' ) , description )
133+ description = build_description (title , description )
73134
74135 parties = []
75136 authors = nuspec .get ('authors' )
@@ -98,7 +159,6 @@ def parse(cls, location):
98159 # This is a SPDX license expression
99160 if 'license' in nuspec :
100161 extracted_license_statement = nuspec .get ('license' )
101- # TODO: try to convert to normal license expression
102162 # Deprecated and not a license expression, just a URL
103163 elif 'licenseUrl' in nuspec :
104164 extracted_license_statement = nuspec .get ('licenseUrl' )
@@ -111,8 +171,10 @@ def parse(cls, location):
111171 description = description or None ,
112172 homepage_url = nuspec .get ('projectUrl' ) or None ,
113173 parties = parties ,
174+ dependencies = list (get_dependencies (nuspec )),
114175 extracted_license_statement = extracted_license_statement ,
115176 copyright = nuspec .get ('copyright' ) or None ,
116177 vcs_url = vcs_url ,
117178 ** urls ,
118179 )
180+
0 commit comments