@@ -222,8 +222,17 @@ def test_bad_pep621_readme(readme, err_match):
222
222
("mit" , "MIT" ),
223
223
("apache-2.0" , "Apache-2.0" ),
224
224
("APACHE-2.0+" , "Apache-2.0+" ),
225
- # TODO: compound expressions
226
- #("mit and (apache-2.0 or bsd-2-clause)", "MIT AND (Apache-2.0 OR BSD-2-Clause)"),
225
+ ("mit AND (apache-2.0 OR bsd-2-clause)" , "MIT AND (Apache-2.0 OR BSD-2-Clause)" ),
226
+ ("(mit)" , "(MIT)" ),
227
+ ("MIT OR Apache-2.0" , "MIT OR Apache-2.0" ),
228
+ ("MIT AND Apache-2.0" , "MIT AND Apache-2.0" ),
229
+ ("MIT AND Apache-2.0+ OR 0BSD" , "MIT AND Apache-2.0+ OR 0BSD" ),
230
+ ("MIT AND (Apache-2.0+ OR (0BSD))" , "MIT AND (Apache-2.0+ OR (0BSD))" ),
231
+ ("MIT OR(mit)" , "MIT OR (MIT)" ),
232
+ ("(mit)AND mit" , "(MIT) AND MIT" ),
233
+ ("MIT OR (MIT OR ( MIT )) AND ((MIT) AND MIT) OR MIT" , "MIT OR (MIT OR (MIT)) AND ((MIT) AND MIT) OR MIT" ),
234
+ ("LICENSEREF-Public-Domain OR cc0-1.0 OR unlicense" , "LicenseRef-Public-Domain OR CC0-1.0 OR Unlicense" ),
235
+ ("mit AND ( apache-2.0+ OR mpl-2.0+ )" , "MIT AND (Apache-2.0+ OR MPL-2.0+)" ),
227
236
# LicenseRef expressions: only the LicenseRef is normalised
228
237
("LiceNseref-Public-DoMain" , "LicenseRef-Public-DoMain" ),
229
238
])
@@ -235,19 +244,143 @@ def test_license_expr(value, license_expression):
235
244
assert 'license' not in info .metadata
236
245
assert info .metadata ['license_expression' ] == license_expression
237
246
238
- def test_license_expr_error ():
247
+ @pytest .mark .parametrize ('invalid_expr' , [
248
+ "LicenseRef-foo_bar" ,
249
+ "LicenseRef-foo~bar" ,
250
+ "LicenseRef-foo:bar" ,
251
+ "LicenseRef-foo[bar]" ,
252
+ "LicenseRef-foo-bar+" ,
253
+ ])
254
+ def test_license_expr_error_licenseref (invalid_expr : str ):
239
255
proj = {
240
256
'name' : 'module1' , 'version' : '1.0' , 'description' : 'x' ,
241
- 'license' : 'LicenseRef-foo_bar' , # Underscore not allowed
257
+ 'license' : invalid_expr ,
242
258
}
243
259
with pytest .raises (config .ConfigError , match = "can only contain" ):
244
260
config .read_pep621_metadata (proj , samples_dir / 'pep621' / 'pyproject.toml' )
245
261
246
- proj ['license' ] = "BSD-33-Clause" # Not a real license
262
+
263
+ @pytest .mark .parametrize ('invalid_expr' , [
264
+ # Not a real licence
265
+ "BSD-33-Clause" ,
266
+ "MIT OR BSD-33-Clause" ,
267
+ "MIT OR (MIT AND BSD-33-Clause)" ,
268
+ ])
269
+ def test_license_expr_error_not_recognised (invalid_expr : str ):
270
+ proj = {
271
+ 'name' : 'module1' , 'version' : '1.0' , 'description' : 'x' ,
272
+ 'license' : invalid_expr ,
273
+ }
247
274
with pytest .raises (config .ConfigError , match = "recognised" ):
248
275
config .read_pep621_metadata (proj , samples_dir / 'pep621' / 'pyproject.toml' )
249
276
250
277
278
+ @pytest .mark .parametrize ('invalid_expr' , [
279
+ # No operator
280
+ "MIT MIT" ,
281
+ "MIT OR (MIT MIT)" ,
282
+ # Only operator
283
+ "AND" ,
284
+ "OR" ,
285
+ "AND AND AND" ,
286
+ "OR OR OR" ,
287
+ "OR AND OR" ,
288
+ "AND OR OR AND OR OR AND" ,
289
+ # Too many operators
290
+ "MIT AND AND MIT" ,
291
+ "MIT OR OR OR MIT" ,
292
+ "MIT AND OR MIT" ,
293
+ # Mixed case operator
294
+ "MIT aND MIT" ,
295
+ "MIT oR MIT" ,
296
+ "MIT AND MIT oR MIT" ,
297
+ # Missing operand
298
+ "MIT AND" ,
299
+ "AND MIT" ,
300
+ "MIT OR" ,
301
+ "OR MIT" ,
302
+ "MIT (AND MIT)" ,
303
+ "(MIT OR) MIT" ,
304
+ # Unbalanced brackets
305
+ ")(" ,
306
+ "(" ,
307
+ ")" ,
308
+ "MIT OR ()" ,
309
+ ") AND MIT" ,
310
+ "MIT OR (" ,
311
+ "MIT OR (MIT))" ,
312
+ # Only brackets
313
+ "()" ,
314
+ "()()" ,
315
+ "()(())" ,
316
+ "( )" ,
317
+ " ( )" ,
318
+ "( ) " ,
319
+ " ( ) " ,
320
+ ])
321
+ def test_license_expr_error (invalid_expr : str ):
322
+ proj = {
323
+ 'name' : 'module1' , 'version' : '1.0' , 'description' : 'x' ,
324
+ 'license' : invalid_expr ,
325
+ }
326
+ with pytest .raises (config .ConfigError , match = "is not a valid" ):
327
+ config .read_pep621_metadata (proj , samples_dir / 'pep621' / 'pyproject.toml' )
328
+
329
+
330
+ @pytest .mark .parametrize ('invalid_expr' , [
331
+ "" ,
332
+ " " ,
333
+ "\t " ,
334
+ "\r " ,
335
+ "\n " ,
336
+ "\f " ,
337
+ " \t \n \r \f " ,
338
+ ])
339
+ def test_license_expr_error_empty (invalid_expr : str ):
340
+ proj = {
341
+ 'name' : 'module1' , 'version' : '1.0' , 'description' : 'x' ,
342
+ 'license' : invalid_expr ,
343
+ }
344
+ with pytest .raises (config .ConfigError , match = "must not be empty" ):
345
+ config .read_pep621_metadata (proj , samples_dir / 'pep621' / 'pyproject.toml' )
346
+
347
+
348
+ @pytest .mark .parametrize ('invalid_expr' , [
349
+ "mit or mit" ,
350
+ "or" ,
351
+ "and" ,
352
+ "MIT and MIT" ,
353
+ "MIT AND MIT or MIT" ,
354
+ "MIT AND (MIT or MIT)" ,
355
+ ])
356
+ def test_license_expr_error_lowercase (invalid_expr : str ):
357
+ proj = {
358
+ 'name' : 'module1' , 'version' : '1.0' , 'description' : 'x' ,
359
+ 'license' : invalid_expr ,
360
+ }
361
+ with pytest .raises (config .ConfigError , match = "must be uppercase" ):
362
+ config .read_pep621_metadata (proj , samples_dir / 'pep621' / 'pyproject.toml' )
363
+
364
+
365
+ @pytest .mark .parametrize ('invalid_expr' , [
366
+ "WITH" ,
367
+ "with" ,
368
+ "WiTh" ,
369
+ "wiTH" ,
370
+ "MIT WITH MIT-Exception" ,
371
+ "(MIT WITH MIT-Exception)" ,
372
+ "MIT OR MIT WITH MIT-Exception" ,
373
+ "MIT WITH MIT-Exception OR (MIT AND MIT)" ,
374
+ ])
375
+ def test_license_expr_error_unsupported_with (invalid_expr : str ):
376
+ proj = {
377
+ 'name' : 'module1' , 'version' : '1.0' , 'description' : 'x' ,
378
+ 'license' : invalid_expr ,
379
+ }
380
+ with pytest .raises (config .ConfigError , match = "not yet supported" ):
381
+ config .read_pep621_metadata (proj , samples_dir / 'pep621' / 'pyproject.toml' )
382
+
383
+
251
384
def test_license_file_defaults_with_old_metadata ():
252
385
metadata = {'module' : 'mymod' , 'author' : '' }
253
386
info = config ._prep_metadata (metadata , samples_dir / 'pep621_license_files' / 'pyproject.toml' )
0 commit comments