diff --git a/src/licensedcode/models.py b/src/licensedcode/models.py index 9947607d51c..a3d4205e322 100644 --- a/src/licensedcode/models.py +++ b/src/licensedcode/models.py @@ -852,6 +852,16 @@ def load_licenses( 'No licenses were loaded. Check to see if the license data files ' f'are available at "{licenses_data_dir}".' ) + if licenses_data_dir == join(data_dir, 'licenses'): + # The built-in license data ships in its own package, so the most + # likely cause here is that this package is not installed. + msg += ( + ' The built-in license data is published in a separate ' + '"licensedcode-data" package: install it with ' + '"pip install licensedcode-data", or install ' + '"scancode-toolkit[licenses]" to also get the prebuilt ' + 'license index.' + ) raise InvalidLicense(msg) return licenses diff --git a/tests/licensedcode/test_license_models.py b/tests/licensedcode/test_license_models.py index bbbe9253755..f29d8f9414c 100644 --- a/tests/licensedcode/test_license_models.py +++ b/tests/licensedcode/test_license_models.py @@ -10,6 +10,8 @@ import os from unittest import TestCase as TestCaseClass +import pytest + from commoncode.testcase import FileBasedTesting from licensedcode import index @@ -660,3 +662,39 @@ def test_get_key_phrases_ignores_nested_key_phrase_markup(self): raise Exception('Exception should be raised') except InvalidRuleRequiredPhrase: pass + + +class TestLoadLicensesFailure(object): + + def test_load_licenses_failure_mentions_licensedcode_data_for_builtin_dir( + self, tmp_path, monkeypatch + ): + # Point the built-in data dir at an empty tree, as it would be when the + # licensedcode-data package is not installed. + data_dir = tmp_path / 'data' + builtin_licenses_dir = data_dir / 'licenses' + builtin_licenses_dir.mkdir(parents=True) + monkeypatch.setattr(models, 'data_dir', str(data_dir)) + + with pytest.raises(models.InvalidLicense) as excinfo: + models.load_licenses(licenses_data_dir=str(builtin_licenses_dir)) + + message = str(excinfo.value) + assert 'No licenses were loaded' in message + assert 'licensedcode-data' in message + + def test_load_licenses_failure_omits_package_hint_for_other_dirs( + self, tmp_path, monkeypatch + ): + # A caller-provided directory has nothing to do with the packaging of + # the built-in license data, so the hint must not be added there. + monkeypatch.setattr(models, 'data_dir', str(tmp_path / 'data')) + custom_licenses_dir = tmp_path / 'custom-licenses' + custom_licenses_dir.mkdir() + + with pytest.raises(models.InvalidLicense) as excinfo: + models.load_licenses(licenses_data_dir=str(custom_licenses_dir)) + + message = str(excinfo.value) + assert 'No licenses were loaded' in message + assert 'licensedcode-data' not in message