From 3e6b3592d126aff62208f319e32b35309d825a3b Mon Sep 17 00:00:00 2001 From: Chin Yeung Li Date: Fri, 31 Aug 2018 16:48:46 +0800 Subject: [PATCH] Fixed #337 - Support more "check" in the `check` command * Add the `--check-licenses` options * Since the `license_expression` is not a required key, the tool will not check or prompt error if this field does not present. Signed-off-by: Chin Yeung Li --- docs/CHANGELOG.rst | 1 + src/attributecode/cmd.py | 24 +++++++++++++++++++-- src/attributecode/model.py | 44 +++++++++++++++++++++++++------------- 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/docs/CHANGELOG.rst b/docs/CHANGELOG.rst index 69b0d767..c7c243a3 100644 --- a/docs/CHANGELOG.rst +++ b/docs/CHANGELOG.rst @@ -7,6 +7,7 @@ * `check` command will not counted INFO message as error when `--verbose` is set * Update `track_change` to `track_changes` * Support `author_file` + * Add `--check-licenses` option to the `check` command 2018-6-25 diff --git a/src/attributecode/cmd.py b/src/attributecode/cmd.py index 94a9ef6c..3ede21db 100644 --- a/src/attributecode/cmd.py +++ b/src/attributecode/cmd.py @@ -196,7 +196,7 @@ def inventory(location, output, mapping, mapping_file, quiet, format, verbose): @click.option('--fetch-license', type=str, nargs=2, metavar='KEY', help=('Fetch licenses text from a DejaCode API. and create .LICENSE side-by-side ' 'with the generated .ABOUT file using data fetched from a DejaCode License Library. ' - 'The "license" key is needed in the input. ' + 'The "license_expression" key is needed in the input. ' 'The following additional options are required:\n\n' 'api_url - URL to the DejaCode License Library API endpoint\n\n' 'api_key - DejaCode API key' @@ -357,6 +357,16 @@ def attrib(location, output, template, mapping, mapping_file, inventory, vartext @click.argument('location', nargs=1, required=True, type=click.Path(exists=True, readable=True, resolve_path=True)) +@click.option('--check-licenses', type=str, nargs=2, metavar='KEY', + help=('Validate the correctness of the license_expression along with the ' + 'license key.' + 'The following additional options are required:\n\n' + 'api_url - URL to the DejaCode License Library API endpoint\n\n' + 'api_key - DejaCode API key' + '\nExample syntax:\n\n' + "about check --check-licenses 'api_url' 'api_key'") +) + @click.option('--verbose', is_flag=True, default=False, help='Show all errors and warnings. ' 'By default, the tool only prints these ' @@ -367,7 +377,7 @@ def attrib(location, output, template, mapping, mapping_file, inventory, vartext @click.help_option('-h', '--help') -def check(location, verbose): +def check(location, check_licenses, verbose): """ Check and validate .ABOUT file(s) at LOCATION for errors and print error messages on the terminal. @@ -379,6 +389,16 @@ def check(location, verbose): errors, abouts = model.collect_inventory(location) + if check_licenses: + # Strip the ' and " for api_url, and api_key from input + api_url = check_licenses[0].strip("'").strip('"') + api_key = check_licenses[1].strip("'").strip('"') + + license_dict, err = model.pre_process_and_fetch_license_dict(abouts, api_url, api_key) + if err: + for e in err: + errors.append(e) + msg_format = '%(sever)s: %(message)s' print_errors = [] number_of_errors = 0 diff --git a/src/attributecode/model.py b/src/attributecode/model.py index 74f0822f..2c36e84d 100644 --- a/src/attributecode/model.py +++ b/src/attributecode/model.py @@ -1410,9 +1410,11 @@ def pre_process_and_fetch_license_dict(abouts, api_url, api_key): key_text_dict = {} captured_license = [] errors = [] + url_not_reachable = False if util.have_network_connection(): if not valid_api_url(api_url): msg = u"URL not reachable. Invalid '--api_url'. License generation is skipped." + url_not_reachable = True errors.append(Error(ERROR, msg)) else: msg = u'Network problem. Please check your Internet connection. License generation is skipped.' @@ -1424,26 +1426,38 @@ def pre_process_and_fetch_license_dict(abouts, api_url, api_key): if auth_error in errors: break if about.license_expression.present: - special_char_in_expression, lic_list = parse_license_expression(about.license_expression.value) + try: + special_char_in_expression, lic_list = parse_license_expression(about.license_expression.value) + except: + # The license_expression cannot be parsed and is incorrectly formatted + msg = (u'The license expression cannot be parsed. Please make sure it is correctly formatted: ' + + about.about_file_path) + errors.append(Error(ERROR, msg)) + continue if special_char_in_expression: msg = (u"The following character(s) cannot be in the licesne_expression: " + str(special_char_in_expression)) errors.append(Error(ERROR, msg)) else: - for lic_key in lic_list: - if not lic_key in captured_license: - detail_list = [] - license_name, license_key, license_text, errs = api.get_license_details_from_api(api_url, api_key, lic_key) - for e in errs: - if e not in errors: - errors.append(e) - if license_key: - captured_license.append(lic_key) - dje_lic_url = dje_lic_urn + license_key - detail_list.append(license_name) - detail_list.append(license_text) - detail_list.append(dje_lic_url) - key_text_dict[license_key] = detail_list + if not url_not_reachable: + for lic_key in lic_list: + if not lic_key in captured_license: + detail_list = [] + license_name, license_key, license_text, errs = api.get_license_details_from_api(api_url, api_key, lic_key) + for e in errs: + if e not in errors: + if "Invalid 'license'" in e.message: + msg = u"Invalid 'license': %s: %s" % (lic_key, about.about_file_path) + errors.append(Error(ERROR, msg)) + else: + errors.append(e) + if license_key: + captured_license.append(lic_key) + dje_lic_url = dje_lic_urn + license_key + detail_list.append(license_name) + detail_list.append(license_text) + detail_list.append(dje_lic_url) + key_text_dict[license_key] = detail_list return key_text_dict, errors