@@ -65,41 +65,29 @@ def quote(s):
65
65
return quoted .replace ('%3A' , ':' )
66
66
67
67
68
- def normalize ( type , namespace , name , version , qualifiers , subpath , encode = True ): # NOQA
68
+ def get_quoter ( encode = True ):
69
69
"""
70
- Return normalized purl components.
70
+ Return quoting callable given an `encode` tri-boolean (True, False or None)
71
71
"""
72
72
if encode is True :
73
- quoting = quote
73
+ return quote
74
74
elif encode is False :
75
- quoting = percent_unquote
75
+ return percent_unquote
76
76
elif encode is None :
77
- quoting = lambda x : x
77
+ return lambda x : x
78
78
79
- if type :
80
- type = type .strip ().lower () # NOQA
81
-
82
- if namespace :
83
- namespace = namespace .strip ().strip ('/' )
84
- if type and type in ('bitbucket' , 'github' , 'pypi' ):
85
- namespace = namespace .lower ()
86
- segments = namespace .split ('/' )
87
- segments = [seg for seg in segments if seg and seg .strip ()]
88
- segments = map (quoting , segments )
89
- namespace = '/' .join (segments )
90
79
91
- if name :
92
- name = name .strip ().strip ('/' )
93
- if type in ('bitbucket' , 'github' , 'pypi' ,):
94
- name = name .lower ()
95
- if type in ('pypi' ,):
96
- name = name .replace ('_' , '-' )
97
- name = quoting (name )
80
+ def normalize_qualifiers (qualifiers , encode = True ):
81
+ """
82
+ Return normalized qualifiers.
98
83
99
- name = name or None
84
+ If `qualifiers` is a dictionary of qualifiers and values and `encode` is true,
85
+ the dictionary is then converted to a string of qualifiers, formatted to the purl specifications.
100
86
101
- if version :
102
- version = quoting (version .strip ())
87
+ If `qualifiers` is a string of qualfiers, formatted to the purl specifications, and `encode`
88
+ is false, the string is then converted to a dictionary of qualifiers and their values.
89
+ """
90
+ quoting = get_quoter (encode )
103
91
104
92
if qualifiers :
105
93
if isinstance (qualifiers , basestring ):
@@ -130,6 +118,42 @@ def normalize(type, namespace, name, version, qualifiers, subpath, encode=True):
130
118
qualifiers = ['{}={}' .format (k , v ) for k , v in qualifiers ]
131
119
qualifiers = '&' .join (qualifiers )
132
120
121
+ return qualifiers or None
122
+
123
+
124
+ def normalize (type , namespace , name , version , qualifiers , subpath , encode = True ): # NOQA
125
+ """
126
+ Return normalized purl components.
127
+ """
128
+ quoting = get_quoter (encode )
129
+
130
+ if type :
131
+ type = type .strip ().lower () # NOQA
132
+
133
+ if namespace :
134
+ namespace = namespace .strip ().strip ('/' )
135
+ if type in ('bitbucket' , 'github' , 'pypi' ):
136
+ namespace = namespace .lower ()
137
+ segments = namespace .split ('/' )
138
+ segments = [seg for seg in segments if seg and seg .strip ()]
139
+ segments = map (quoting , segments )
140
+ namespace = '/' .join (segments )
141
+
142
+ if name :
143
+ name = name .strip ().strip ('/' )
144
+ if type in ('bitbucket' , 'github' , 'pypi' ,):
145
+ name = name .lower ()
146
+ if type in ('pypi' ,):
147
+ name = name .replace ('_' , '-' )
148
+ name = quoting (name )
149
+
150
+ name = name or None
151
+
152
+ if version :
153
+ version = quoting (version .strip ())
154
+
155
+ qualifiers = normalize_qualifiers (qualifiers , encode )
156
+
133
157
if subpath :
134
158
segments = subpath .split ('/' )
135
159
segments = [quoting (s ) for s in segments if s and s .strip ()
@@ -167,8 +191,8 @@ def __new__(self, type=None, namespace=None, name=None, # NOQA
167
191
raise ValueError ('Invalid purl: {} argument must be a string: {}.'
168
192
.format (key , repr (value )))
169
193
170
- if qualifiers and not isinstance (qualifiers , (dict , OrderedDict ,)):
171
- raise ValueError ('Invalid purl: {} argument must be a dict: {}.'
194
+ if qualifiers and not isinstance (qualifiers , (basestring , dict , OrderedDict ,)):
195
+ raise ValueError ('Invalid purl: {} argument must be a dict or a string : {}.'
172
196
.format ('qualifiers' , repr (qualifiers )))
173
197
174
198
type , namespace , name , version , qualifiers , subpath = normalize (# NOQA
0 commit comments