@@ -143,11 +143,13 @@ def add_referenced_license_matches_for_package(resource, codebase, no_licenses):
143
143
yield resource
144
144
145
145
146
- def add_referenced_license_detection_from_package (resource , codebase ):
146
+ def add_referenced_license_detection_from_package (resource , codebase , no_licenses ):
147
147
"""
148
148
Return an updated ``resource`` saving it in place, after adding new license
149
149
matches (licenses and license_expressions) following their Rule
150
- ``referenced_filenames`` if it is pointing to a package.
150
+ ``referenced_filenames`` if it is pointing to a package. If there is no
151
+ top level packages, check for License/Readme files at codebase root and
152
+ add licenses from there.
151
153
"""
152
154
if TRACE :
153
155
logger_debug (f'packagedcode.licensing: add_referenced_license_matches_from_package: resource: { resource .path } ' )
@@ -178,25 +180,45 @@ def add_referenced_license_detection_from_package(resource, codebase):
178
180
if not has_reference_to_package :
179
181
continue
180
182
181
- for_packages = resource .for_packages
182
- for package_uid in for_packages :
183
-
184
- for codebase_package in codebase_packages :
185
- if codebase_package ["package_uid" ] == package_uid :
186
- break
183
+ if not codebase_packages :
184
+ root_path = codebase .root .path
185
+ root_resource = codebase .get_resource (path = root_path )
186
+ sibling_license_detections , _le = get_license_detections_from_sibling_file (
187
+ root_resource , codebase , no_licenses
188
+ )
189
+ if TRACE :
190
+ logger_debug (
191
+ f'packagedcode.licensing: add_referenced_license_matches_from_package: root_path: { root_path } '
192
+ f'sibling_license_detections: { sibling_license_detections } '
193
+ )
187
194
188
- pkg_detections = codebase_package ["license_detections" ]
189
- for pkg_detection in pkg_detections :
195
+ for sibling_detection in sibling_license_detections :
190
196
modified = True
191
197
detection_modified = True
192
- matches .extend (pkg_detection ["matches" ])
193
-
198
+ matches .extend (sibling_detection ["matches" ])
199
+ analysis = DetectionCategory .UNKNOWN_REFERENCE_IN_FILE_TO_NONEXISTENT_PACKAGE .value
200
+
201
+ else :
202
+ for_packages = resource .for_packages
203
+ for package_uid in for_packages :
204
+
205
+ for codebase_package in codebase_packages :
206
+ if codebase_package ["package_uid" ] == package_uid :
207
+ break
208
+
209
+ pkg_detections = codebase_package ["license_detections" ]
210
+ for pkg_detection in pkg_detections :
211
+ modified = True
212
+ detection_modified = True
213
+ matches .extend (pkg_detection ["matches" ])
214
+ analysis = DetectionCategory .UNKNOWN_REFERENCE_IN_FILE_TO_PACKAGE .value
215
+
194
216
if not detection_modified :
195
217
continue
196
218
197
219
reasons , license_expression = get_detected_license_expression (
198
220
matches = matches ,
199
- analysis = DetectionCategory . UNKNOWN_REFERENCE_IN_FILE_TO_PACKAGE . value ,
221
+ analysis = analysis ,
200
222
post_scan = True ,
201
223
)
202
224
detection ["license_expression" ] = str (license_expression )
@@ -249,24 +271,35 @@ def add_license_from_sibling_file(resource, codebase, no_licenses):
249
271
package ["license_detections" ] = license_detections
250
272
package ["declared_license_expression" ] = license_expression
251
273
package ["declared_license_expression_spdx" ] = str (build_spdx_license_expression (
252
- license_expression = pkg ["declared_license_expression" ],
274
+ license_expression = package ["declared_license_expression" ],
253
275
licensing = get_cache ().licensing ,
254
276
))
255
277
256
278
codebase .save_resource (resource )
257
279
return package
258
280
259
281
282
+ def is_legal_or_readme (resource ):
283
+ is_legal = check_resource_name_start_and_end (resource = resource , STARTS_ENDS = LEGAL_STARTS_ENDS )
284
+ is_readme = check_resource_name_start_and_end (resource = resource , STARTS_ENDS = README_STARTS_ENDS )
285
+ if is_legal or is_readme :
286
+ return True
287
+
288
+ return False
289
+
290
+
260
291
def get_license_detections_from_sibling_file (resource , codebase , no_licenses ):
261
292
262
293
siblings = []
263
294
264
295
if resource .has_parent ():
265
296
for sibling in resource .siblings (codebase ):
266
- is_legal = check_resource_name_start_and_end (resource = sibling , STARTS_ENDS = LEGAL_STARTS_ENDS )
267
- is_readme = check_resource_name_start_and_end (resource = sibling , STARTS_ENDS = README_STARTS_ENDS )
268
- if is_legal or is_readme :
297
+ if is_legal_or_readme (resource = sibling ):
269
298
siblings .append (sibling )
299
+ elif resource .has_children :
300
+ for child in resource .children (codebase ):
301
+ if is_legal_or_readme (resource = child ):
302
+ siblings .append (child )
270
303
271
304
if not siblings :
272
305
return [], None
@@ -287,7 +320,10 @@ def get_license_detections_from_sibling_file(resource, codebase, no_licenses):
287
320
if not license_detections :
288
321
return [], None
289
322
290
- license_expression = get_license_expression_from_detection_mappings (license_detections )
323
+ license_expression = get_license_expression_from_detection_mappings (
324
+ detections = license_detections ,
325
+ valid_expression = False ,
326
+ )
291
327
return license_detections , license_expression
292
328
293
329
@@ -383,9 +419,14 @@ def get_license_expression_from_matches(license_matches, relation='AND', unique=
383
419
if not license_matches :
384
420
return
385
421
386
- license_expressions = [
387
- match .rule .license_expression for match in license_matches
388
- ]
422
+ if type (license_matches [0 ]) == dict :
423
+ license_expressions = [
424
+ match ['license_expression' ] for match in license_matches
425
+ ]
426
+ else :
427
+ license_expressions = [
428
+ match .rule .license_expression for match in license_matches
429
+ ]
389
430
390
431
if len (license_expressions ) == 1 :
391
432
license_expression = str (license_expressions [0 ])
@@ -397,10 +438,22 @@ def get_license_expression_from_matches(license_matches, relation='AND', unique=
397
438
return license_expression
398
439
399
440
400
- def get_license_expression_from_detection_mappings (detections , relation = 'AND' , unique = True ):
441
+ def get_license_expression_from_detection_mappings (
442
+ detections ,
443
+ relation = 'AND' ,
444
+ unique = True ,
445
+ valid_expression = False ,
446
+ ):
401
447
402
448
expressions = []
403
449
for detection in detections :
450
+ if valid_expression :
451
+ if not detection ["license_expression" ]:
452
+ expressions .append (
453
+ get_license_expression_from_matches (detection ["matches" ])
454
+ )
455
+ continue
456
+
404
457
expressions .append (detection ["license_expression" ])
405
458
406
459
return str (
0 commit comments