8
8
#
9
9
10
10
import xmltodict
11
+ from packageurl import PackageURL
11
12
12
13
from packagedcode import models
13
14
from packagedcode .utils import build_description
14
15
15
16
"""
16
17
Handle NuGet packages and their manifests.
17
18
"""
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
+ )
19
80
20
81
21
82
def get_urls (name , version , ** kwargs ):
@@ -46,7 +107,7 @@ class NugetNuspecHandler(models.DatafileHandler):
46
107
47
108
@classmethod
48
109
def parse (cls , location ):
49
- with open (location , 'rb' ) as loc :
110
+ with open (location , 'rb' ) as loc :
50
111
parsed = xmltodict .parse (loc )
51
112
52
113
if not parsed :
@@ -62,14 +123,14 @@ def parse(cls, location):
62
123
63
124
# Summary: A short description of the package for UI display. If omitted, a
64
125
# 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' ))
66
127
67
128
# title: A human-friendly title of the package, typically used in UI
68
129
# displays as on nuget.org and the Package Manager in Visual Studio. If not
69
130
# specified, the package ID is used.
70
131
title = nuspec .get ('title' )
71
132
if title and title != name :
72
- description = build_description (nuspec . get ( ' title' ) , description )
133
+ description = build_description (title , description )
73
134
74
135
parties = []
75
136
authors = nuspec .get ('authors' )
@@ -98,7 +159,6 @@ def parse(cls, location):
98
159
# This is a SPDX license expression
99
160
if 'license' in nuspec :
100
161
extracted_license_statement = nuspec .get ('license' )
101
- # TODO: try to convert to normal license expression
102
162
# Deprecated and not a license expression, just a URL
103
163
elif 'licenseUrl' in nuspec :
104
164
extracted_license_statement = nuspec .get ('licenseUrl' )
@@ -111,8 +171,10 @@ def parse(cls, location):
111
171
description = description or None ,
112
172
homepage_url = nuspec .get ('projectUrl' ) or None ,
113
173
parties = parties ,
174
+ dependencies = list (get_dependencies (nuspec )),
114
175
extracted_license_statement = extracted_license_statement ,
115
176
copyright = nuspec .get ('copyright' ) or None ,
116
177
vcs_url = vcs_url ,
117
178
** urls ,
118
179
)
180
+
0 commit comments