Skip to content

Commit 591655e

Browse files
committed
Fixed #523 - Add option to identify worksheet input
* Able to identify worksheet name for the xlsx input for the tool to work with * Enhance error handling Signed-off-by: Chin Yeung Li <[email protected]>
1 parent f0b8cd0 commit 591655e

File tree

12 files changed

+140
-59
lines changed

12 files changed

+140
-59
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Changelog
55

66
* Fixed the transform code for xlsx and json
77
* Remove irrelevant error for attrib
8+
* Add support to identify worksheet name for XLSX input
89

910

1011
2022-10-24

about.ABOUT

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
about_resource: .
22
name: AboutCode-toolkit
3-
version: 7.2.1
3+
version: 7.3.0
44
author: Jillian Daguil, Chin Yeung Li, Philippe Ombredanne, Thomas Druez
55
copyright: Copyright (c) nexB Inc.
66
description: |

docs/source/reference.rst

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,19 @@ Options
6363
--api_url URL URL to DejaCode License Library.
6464
--api_key KEY API Key for the DejaCode License Library
6565
--min-license-score INTEGER Attribute components that have license score
66-
higher than the defined --min-license-score.
66+
higher than or equal to the defined --min-
67+
license-score.
6768
--scancode Indicate the input JSON file is from
68-
scancode toolkit.
69+
scancode_toolkit.
6970
--reference DIR Path to a directory with reference files where
70-
"license_file" and/or "notice_file" located.
71-
--template FILE Path to an optional custom attribution template to
72-
generate the attribution document. If not provided
73-
the default built-in template is used.
74-
--vartext <key>=<value> Add variable text as key=value for use in a custom
75-
attribution template.
71+
"license_file" and/or "notice_file" located.
72+
--template FILE Path to an optional custom attribution template
73+
to generate the attribution document. If not
74+
provided the default built-in template is used.
75+
--vartext <key>=<value> Add variable text as key=value for use in a
76+
custom attribution template.
77+
--worksheet name The worksheet name from the INPUT. (Default:
78+
the "active" worksheet)
7679
-q, --quiet Do not print error or warning messages.
7780
--verbose Show all error and warning messages.
7881
-h, --help Show this message and exit.
@@ -149,6 +152,13 @@ Details
149152
{{ vartext['title'] }}
150153
{{ vartext['header'] }}
151154
155+
--worksheet
156+
157+
This option identify the worksheet name from the XLSX input to work with.
158+
If no worksheet is defined, the "active" worksheet will be used
159+
160+
$ about attrib --worksheet BOM /home/project/audit.xlsx OUTPUT
161+
152162
--verbose
153163
154164
This option tells the tool to show all errors found.
@@ -326,28 +336,22 @@ Options
326336

327337
.. code-block:: none
328338
329-
--android Generate MODULE_LICENSE_XXX (XXX will be
330-
replaced by license key) and NOTICE as the same
331-
design as from Android.
332-
--fetch-license Fetch license data and text files from the
333-
ScanCode LicenseDB.
334-
--fetch-license-djc api_url api_key Fetch licenses data from DejaCode License
335-
Library and create <license>.LICENSE
336-
side-by-side with the generated .ABOUT file.
337-
The following additional options are required:
338-
339-
api_url - URL to the DejaCode License Library
340-
API endpoint
341-
342-
api_key - DejaCode API key
343-
Example syntax:
344-
345-
about gen --fetch-license-djc api_url api_key
346-
--reference PATH Path to a directory with reference license
347-
data and text files.
348-
-q, --quiet Do not print any error/warning.
349-
--verbose Show all the errors and warning.
350-
-h, --help Show this message and exit.
339+
--android Generate MODULE_LICENSE_XXX (XXX will be
340+
replaced by license key) and NOTICE as the
341+
same design as from Android.
342+
--fetch-license Fetch license data and text files from the
343+
ScanCode LicenseDB.
344+
--fetch-license-djc api_url api_key
345+
Fetch license data and text files from a
346+
DejaCode License Library API URL using the
347+
API KEY.
348+
--reference DIR Path to a directory with reference license
349+
data and text files.
350+
--worksheet name The worksheet name from the INPUT. (Default:
351+
the "active" worksheet)
352+
-q, --quiet Do not print error or warning messages.
353+
--verbose Show all error and warning messages.
354+
-h, --help Show this message and exit.
351355
352356
Purpose
353357
-------
@@ -405,6 +409,13 @@ Details
405409
406410
$ about gen --reference /home/licenses_notices/ LOCATION OUTPUT
407411
412+
--worksheet
413+
414+
This option identify the worksheet name from the XLSX input to work with.
415+
If no worksheet is defined, the "active" worksheet will be used
416+
417+
$ about gen --worksheet BOM LOCATION OUTPUT
418+
408419
--verbose
409420
410421
This option tells the tool to show all errors found.
@@ -428,13 +439,13 @@ Options
428439

429440
.. code-block:: none
430441
431-
--djc api_url api_key Fetch licenses data from DejaCode License
432-
Library and create <license>.LICENSE to the
433-
OUTPUT location.
434-
--scancode Indicate the input JSON file is from
442+
--djc api_url api_key Fetch licenses from a DejaCode License Library.
443+
--scancode Indicate the input JSON file is from
435444
scancode_toolkit.
436-
--verbose Show all the errors and warning.
437-
-h, --help Show this message and exit.
445+
--worksheet name The worksheet name from the INPUT. (Default: the
446+
"active" worksheet)
447+
--verbose Show all error and warning messages.
448+
-h, --help Show this message and exit.
438449
439450
Purpose
440451
-------
@@ -467,6 +478,13 @@ Details
467478
468479
$ about gen_license --scancode /home/project/scancode-license-detection.json OUTPUT
469480
481+
--worksheet
482+
483+
This option identify the worksheet name from the XLSX input to work with.
484+
If no worksheet is defined, the "active" worksheet will be used
485+
486+
$ about gen_license --worksheet BOM /home/project/bom-v0.10.xlsx OUTPUT
487+
470488
--verbose
471489
472490
This option tells the tool to show all errors found.
@@ -594,7 +612,9 @@ Options
594612
.. code-block:: none
595613
596614
-c, --configuration FILE Path to an optional YAML configuration file. See
597-
--help-format for format help.
615+
--help-format for format help.
616+
--worksheet name The worksheet name from the INPUT. (Default: the
617+
"active" worksheet)
598618
--help-format Show configuration file format help and exit.
599619
-q, --quiet Do not print error or warning messages.
600620
--verbose Show all error and warning messages.
@@ -617,6 +637,13 @@ Details
617637
618638
$ about transform -c 'path to the YAML configuration file' LOCATION OUTPUT
619639
640+
--worksheet
641+
642+
This option identify the worksheet name from the XLSX input to work with.
643+
If no worksheet is defined, the "active" worksheet will be used
644+
645+
$ about transform -c 'path to the YAML configuration file' --worksheet BOM /project/bom-v.20.xlsx OUTPUT
646+
620647
--help-format
621648
622649
Show configuration file format help and exit.

src/attributecode/cmd.py

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ def inventory(location, output, format, quiet, verbose): # NOQA
239239
type=click.Path(exists=True, file_okay=False, readable=True, resolve_path=True),
240240
help='Path to a directory with reference license data and text files.')
241241

242+
@click.option('--worksheet',
243+
metavar='name',
244+
help='The worksheet name from the INPUT. (Default: the "active" worksheet)')
245+
242246
@click.option('-q', '--quiet',
243247
is_flag=True,
244248
help='Do not print error or warning messages.')
@@ -248,7 +252,7 @@ def inventory(location, output, format, quiet, verbose): # NOQA
248252
help='Show all error and warning messages.')
249253

250254
@click.help_option('-h', '--help')
251-
def gen(location, output, android, fetch_license, fetch_license_djc, reference, quiet, verbose):
255+
def gen(location, output, android, fetch_license, fetch_license_djc, reference, worksheet, quiet, verbose):
252256
"""
253257
Given a CSV/JSON/XLSX inventory, generate ABOUT files in the output location.
254258
@@ -264,13 +268,17 @@ def gen(location, output, android, fetch_license, fetch_license_djc, reference,
264268
if not location.endswith(('.csv', '.json', '.xlsx')):
265269
raise click.UsageError('ERROR: Invalid input file extension: must be one .csv or .json or .xlsx.')
266270

271+
if worksheet and not location.endswith('.xlsx'):
272+
raise click.UsageError('ERROR: --worksheet option only works with .xlsx input.')
273+
267274
errors, abouts = generate_about_files(
268275
location=location,
269276
base_dir=output,
270277
android=android,
271278
reference_dir=reference,
272279
fetch_license=fetch_license,
273280
fetch_license_djc=fetch_license_djc,
281+
worksheet=worksheet
274282
)
275283

276284
errors_count = report_errors(errors, quiet, verbose, log_file_loc=output + '-error.log')
@@ -309,12 +317,16 @@ def gen(location, output, android, fetch_license, fetch_license_djc, reference,
309317
is_flag=True,
310318
help='Indicate the input JSON file is from scancode_toolkit.')
311319

320+
@click.option('--worksheet',
321+
metavar='name',
322+
help='The worksheet name from the INPUT. (Default: the "active" worksheet)')
323+
312324
@click.option('--verbose',
313325
is_flag=True,
314326
help='Show all error and warning messages.')
315327

316328
@click.help_option('-h', '--help')
317-
def gen_license(location, output, djc, scancode, verbose):
329+
def gen_license(location, output, djc, scancode, worksheet, verbose):
318330
"""
319331
Fetch licenses (Default: ScanCode LicenseDB) in the license_expression field and save to the output location.
320332
@@ -327,10 +339,13 @@ def gen_license(location, output, djc, scancode, verbose):
327339
api_key = ''
328340
errors = []
329341

342+
if worksheet and not location.endswith('.xlsx'):
343+
raise click.UsageError('ERROR: --worksheet option only works with .xlsx input.')
344+
330345
log_file_loc = os.path.join(output, 'error.log')
331346

332347
if location.endswith('.csv') or location.endswith('.json') or location.endswith('.xlsx'):
333-
errors, abouts = collect_inventory_license_expression(location=location, scancode=scancode)
348+
errors, abouts = collect_inventory_license_expression(location=location, scancode=scancode, worksheet=worksheet)
334349
if errors:
335350
severe_errors_count = report_errors(errors, quiet=False, verbose=verbose, log_file_loc=log_file_loc)
336351
sys.exit(severe_errors_count)
@@ -440,6 +455,10 @@ def validate_template(ctx, param, value):
440455
metavar='<key>=<value>',
441456
help='Add variable text as key=value for use in a custom attribution template.')
442457

458+
@click.option('--worksheet',
459+
metavar='name',
460+
help='The worksheet name from the INPUT. (Default: the "active" worksheet)')
461+
443462
@click.option('-q', '--quiet',
444463
is_flag=True,
445464
help='Do not print error or warning messages.')
@@ -449,7 +468,7 @@ def validate_template(ctx, param, value):
449468
help='Show all error and warning messages.')
450469

451470
@click.help_option('-h', '--help')
452-
def attrib(input, output, api_url, api_key, scancode, min_license_score, reference, template, vartext, quiet, verbose):
471+
def attrib(input, output, api_url, api_key, scancode, min_license_score, reference, template, vartext, worksheet, quiet, verbose):
453472
"""
454473
Generate an attribution document at OUTPUT using JSON, CSV or XLSX or .ABOUT files at INPUT.
455474
@@ -464,6 +483,9 @@ def attrib(input, output, api_url, api_key, scancode, min_license_score, referen
464483
license_dict = {}
465484
errors = []
466485

486+
if worksheet and not input.endswith('.xlsx'):
487+
raise click.UsageError('ERROR: --worksheet option only works with .xlsx input.')
488+
467489
if not quiet:
468490
print_version()
469491
click.echo('Generating attribution...')
@@ -501,7 +523,8 @@ def attrib(input, output, api_url, api_key, scancode, min_license_score, referen
501523
location=input,
502524
from_attrib=from_attrib,
503525
scancode=scancode,
504-
reference_dir=reference
526+
reference_dir=reference,
527+
worksheet=worksheet
505528
)
506529

507530
else:
@@ -765,6 +788,10 @@ def print_config_help(ctx, param, value):
765788
help='Path to an optional YAML configuration file. See --help-format for '
766789
'format help.')
767790

791+
@click.option('--worksheet',
792+
metavar='name',
793+
help='The worksheet name from the INPUT. (Default: the "active" worksheet)')
794+
768795
@click.option('--help-format',
769796
is_flag=True, is_eager=True, expose_value=False,
770797
callback=print_config_help,
@@ -779,7 +806,7 @@ def print_config_help(ctx, param, value):
779806
help='Show all error and warning messages.')
780807

781808
@click.help_option('-h', '--help')
782-
def transform(location, output, configuration, quiet, verbose): # NOQA
809+
def transform(location, output, configuration, worksheet, quiet, verbose): # NOQA
783810
"""
784811
Transform the CSV/JSON/XLSX file at LOCATION by applying renamings, filters and checks
785812
and then write a new CSV/JSON/XLSX to OUTPUT.
@@ -788,6 +815,9 @@ def transform(location, output, configuration, quiet, verbose): # NOQA
788815
789816
OUTPUT: Path to CSV/JSON/XLSX inventory file to create.
790817
"""
818+
if worksheet and not location.endswith('.xlsx'):
819+
raise click.UsageError('ERROR: --worksheet option only works with .xlsx input.')
820+
791821
if not configuration:
792822
transformer = Transformer.default()
793823
else:
@@ -807,11 +837,16 @@ def transform(location, output, configuration, quiet, verbose): # NOQA
807837
elif location.endswith('.json'):
808838
new_data, errors = transform_json(location)
809839
elif location.endswith('.xlsx'):
810-
new_data, errors = transform_excel(location)
840+
new_data, errors = transform_excel(location, worksheet)
811841

812842
if not errors:
813843
updated_data, errors = transform_data(new_data, transformer)
814844

845+
if not updated_data:
846+
msg = 'The input is empty. Nothing is transformed.'
847+
click.echo(msg)
848+
sys.exit(0)
849+
815850
if not errors:
816851
if output.endswith('.csv'):
817852
write_csv(output, updated_data)

src/attributecode/gen.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def check_about_resource_filename(arp):
116116
return ''
117117

118118

119-
def load_inventory(location, from_attrib=False, base_dir=None, scancode=False, reference_dir=None):
119+
def load_inventory(location, from_attrib=False, base_dir=None, scancode=False, reference_dir=None, worksheet=None):
120120
"""
121121
Load the inventory file at `location` for ABOUT and LICENSE files stored in
122122
the `base_dir`. Return a list of errors and a list of About objects
@@ -140,7 +140,7 @@ def load_inventory(location, from_attrib=False, base_dir=None, scancode=False, r
140140
return errors, abouts
141141
inventory = load_csv(location)
142142
elif location.endswith('.xlsx'):
143-
dup_cols_err, inventory = load_excel(location)
143+
dup_cols_err, inventory = load_excel(location, worksheet)
144144
if dup_cols_err:
145145
errors.extend(dup_cols_err)
146146
return errors, abouts
@@ -266,7 +266,7 @@ def update_about_resource(self):
266266
pass
267267

268268

269-
def generate(location, base_dir, android=None, reference_dir=None, fetch_license=False, fetch_license_djc=False):
269+
def generate(location, base_dir, android=None, reference_dir=None, fetch_license=False, fetch_license_djc=False, worksheet=None):
270270
"""
271271
Load ABOUT data from a CSV inventory at `location`. Write ABOUT files to
272272
base_dir. Return errors and about objects.
@@ -293,7 +293,8 @@ def generate(location, base_dir, android=None, reference_dir=None, fetch_license
293293
errors, abouts = load_inventory(
294294
location=location,
295295
base_dir=bdir,
296-
reference_dir=reference_dir
296+
reference_dir=reference_dir,
297+
worksheet=worksheet
297298
)
298299

299300
if gen_license:

src/attributecode/model.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,7 +1392,7 @@ def collect_abouts_license_expression(location):
13921392
return errors, abouts
13931393

13941394

1395-
def collect_inventory_license_expression(location, scancode=False):
1395+
def collect_inventory_license_expression(location, scancode=False, worksheet=None):
13961396
"""
13971397
Read the inventory file at location and return a list of ABOUT objects without
13981398
validation. The purpose of this is to speed up the process for `gen_license` command.
@@ -1410,11 +1410,11 @@ def collect_inventory_license_expression(location, scancode=False):
14101410
if location.endswith('.csv'):
14111411
inventory = gen.load_csv(location)
14121412
elif location.endswith('.xlsx'):
1413-
_dup_cols_err, inventory = gen.load_excel(location)
1413+
_dup_cols_err, inventory = gen.load_excel(location, worksheet)
14141414
else:
14151415
inventory = gen.load_json(location)
14161416
# Check if 'license_expression' field is in the input
1417-
if not 'license_expression' in inventory[0]:
1417+
if not inventory or not 'license_expression' in inventory[0]:
14181418
errors.append(Error(CRITICAL, "No 'license_expression' field in the input."))
14191419
return errors, abouts
14201420

0 commit comments

Comments
 (0)