Skip to content

Commit 1f135e2

Browse files
committed
#492 - redefine logic for verbose and quiet
* Previous code will store all the wanrning (INFO, NOTSET, DEBUG) even the `verbose` flag is not set in the log file. We should only store errors for whatever users define instead of sotring everything * Update tests and changelog Signed-off-by: Chin Yeung Li <[email protected]>
1 parent 76aa751 commit 1f135e2

File tree

8 files changed

+73
-77
lines changed

8 files changed

+73
-77
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* Bump PyYAML to 6.0
2121
* Add '%" as a supported character
2222
* Update default template
23+
* All errors are logged if and only if the `verbose` option is set. Otherwise, ony 'Critical' and 'Warning' errors will be showed/logged
2324

2425
2021-04-02
2526
Release 6.0.0

src/attributecode/cmd.py

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -810,41 +810,44 @@ def report_errors(errors, quiet, verbose, log_file_loc=None):
810810
file.
811811
Return True if there were severe error reported.
812812
"""
813-
messages, severe_errors_count = get_error_messages(errors, quiet, verbose)
814-
for msg in messages:
815-
click.echo(msg)
816-
if log_file_loc and errors:
817-
log_msgs, _ = get_error_messages(errors, quiet=False, verbose=True)
818-
with io.open(log_file_loc, 'w', encoding='utf-8', errors='replace') as lf:
819-
lf.write('\n'.join(log_msgs))
820-
click.echo("Error log: " + log_file_loc)
813+
severe_errors_count = 0
814+
if errors:
815+
log_msgs, severe_errors_count = get_error_messages(errors, verbose)
816+
if not quiet:
817+
for msg in log_msgs:
818+
click.echo(msg)
819+
if log_file_loc:
820+
with io.open(log_file_loc, 'w', encoding='utf-8', errors='replace') as lf:
821+
lf.write('\n'.join(log_msgs))
822+
click.echo("Error log: " + log_file_loc)
821823
return severe_errors_count
822824

823825

824-
def get_error_messages(errors, quiet=False, verbose=False):
826+
def get_error_messages(errors, verbose=False):
825827
"""
826828
Return a tuple of (list of error message strings to report,
827829
severe_errors_count) given an `errors` list of Error objects and using the
828-
`quiet` and `verbose` flags.
830+
`verbose` flags.
829831
"""
830-
errors = unique(errors)
831-
severe_errors = filter_errors(errors, WARNING)
832+
if verbose:
833+
severe_errors = errors
834+
else:
835+
severe_errors = filter_errors(errors, WARNING)
836+
837+
severe_errors = unique(severe_errors)
832838
severe_errors_count = len(severe_errors)
833839

834840
messages = []
835841

836-
if severe_errors and not quiet:
842+
if severe_errors:
837843
error_msg = 'Command completed with {} errors or warnings.'.format(severe_errors_count)
838844
messages.append(error_msg)
839845

840-
for severity, message in errors:
846+
for severity, message in severe_errors:
841847
sevcode = severities.get(severity) or 'UNKNOWN'
842848
msg = '{sevcode}: {message}'.format(**locals())
843-
if not quiet:
844-
if verbose:
845-
messages.append(msg)
846-
elif severity >= WARNING:
847-
messages.append(msg)
849+
messages.append(msg)
850+
848851
return messages, severe_errors_count
849852

850853
######################################################################

src/attributecode/gen.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ def load_inventory(location, from_attrib=False, base_dir=None, scancode=False, r
176176
errors.append(Error(CRITICAL, msg))
177177
return errors, abouts
178178

179+
custom_fields_list = []
179180
for fields in inventory:
180181
# check does the input contains the required fields
181182
required_fields = model.About.required_fields
@@ -220,15 +221,19 @@ def load_inventory(location, from_attrib=False, base_dir=None, scancode=False, r
220221
running_inventory=False,
221222
reference_dir=reference_dir,
222223
)
223-
"""
224-
# 'about_resource' field will be generated during the process.
225-
# No error need to be raise for the missing 'about_resource'.
226-
for e in ld_errors:
227-
if e.message == 'Field about_resource is required':
228-
ld_errors.remove(e)
229-
"""
230-
errors.extend(ld_errors)
224+
225+
for severity, message in ld_errors:
226+
if 'Custom Field' in message:
227+
field_name = message.replace('Custom Field: ', '').strip()
228+
if not field_name in custom_fields_list:
229+
custom_fields_list.append(field_name)
230+
else:
231+
errors.append(Error(severity, message))
232+
231233
abouts.append(about)
234+
if custom_fields_list:
235+
custom_fields_err_msg = 'Field ' + str(custom_fields_list) + ' is a custom field.'
236+
errors.append(Error(INFO, custom_fields_err_msg))
232237
# Covert the license_score value from string to list of int
233238
# The licesne_score is not in the spec but is specify in the scancode license scan.
234239
# This key will be treated as a custom string field. Therefore, we need to

src/attributecode/model.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -928,7 +928,7 @@ def hydrate(self, fields):
928928
continue
929929
"""
930930

931-
msg = 'Field %(orig_name)s is a custom field.'
931+
msg = 'Custom Field: %(orig_name)s'
932932
errors.append(Error(INFO, msg % locals()))
933933
# is this a known one?
934934
custom_field = self.custom_fields.get(name)
@@ -969,6 +969,7 @@ def process(self, fields, about_file_path, running_inventory=False,
969969
afp = self.about_file_path
970970

971971
errors = self.hydrate(fields)
972+
972973
# We want to copy the license_files before the validation
973974
if reference_dir and not from_attrib:
974975
copy_err = copy_license_notice_files(
@@ -1341,10 +1342,9 @@ def collect_inventory(location):
13411342
for about_loc in about_locations:
13421343
about_file_path = util.get_relative_path(input_location, about_loc)
13431344
about = About(about_loc, about_file_path)
1344-
# Insert about_file_path reference to the error
13451345
for severity, message in about.errors:
1346-
if 'is a custom field' in message:
1347-
field_name = message.replace('Field', '').replace('is a custom field.', '').strip()
1346+
if 'Custom Field' in message:
1347+
field_name = message.replace('Custom Field: ', '').strip()
13481348
if not field_name in custom_fields_list:
13491349
custom_fields_list.append(field_name)
13501350
else:

src/attributecode/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ def filter_errors(errors, minimum_severity=WARNING):
574574
Return a list of unique `errors` Error object filtering errors that have a
575575
severity below `minimum_severity`.
576576
"""
577-
return unique([e for e in errors if e.severity >= minimum_severity])
577+
return [e for e in errors if e.severity >= minimum_severity]
578578

579579

580580
def create_dir(location):

tests/test_cmd.py

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ def test_report_errors(capsys):
4444
Error(NOTSET, 'msg4'),
4545
]
4646
ec = cmd.report_errors(errors, quiet=False, verbose=True, log_file_loc=None)
47-
assert 3 == ec
47+
assert 6 == ec
4848
out, err = capsys.readouterr()
4949
expected_out = [
50-
'Command completed with 3 errors or warnings.',
50+
'Command completed with 6 errors or warnings.',
5151
'CRITICAL: msg1',
5252
'ERROR: msg2',
5353
'INFO: msg3',
@@ -91,7 +91,7 @@ def test_report_errors_with_quiet_ignores_verbose_flag(capsys):
9191
Error(WARNING, 'msg4'),
9292
]
9393
severe_errors_count = cmd.report_errors(errors, quiet=True, verbose=True)
94-
assert severe_errors_count == 3
94+
assert severe_errors_count == 6
9595
out, err = capsys.readouterr()
9696
assert '' == out
9797
assert '' == err
@@ -125,17 +125,19 @@ def test_report_errors_with_verbose_flag(capsys):
125125
Error(WARNING, 'msg4'),
126126
]
127127
severe_errors_count = cmd.report_errors(errors, quiet=False, verbose=True)
128-
assert severe_errors_count == 3
128+
assert severe_errors_count == 6
129129
out, err = capsys.readouterr()
130130
expected_out = [
131-
'Command completed with 3 errors or warnings.',
131+
'Command completed with 6 errors or warnings.',
132132
'CRITICAL: msg1',
133133
'ERROR: msg2',
134134
'INFO: msg3',
135135
'WARNING: msg4',
136136
'DEBUG: msg4',
137137
'NOTSET: msg4'
138138
]
139+
print("@@@@@@@@@@@@@@@@@@@@@@@@")
140+
print(out.splitlines(False))
139141
assert expected_out == out.splitlines(False)
140142
assert '' == err
141143

@@ -157,7 +159,7 @@ def test_report_errors_can_write_to_logfile():
157159
with io.open(result_file, 'r', encoding='utf-8', errors='replace') as rf:
158160
result = rf.read()
159161
expected = [
160-
'Command completed with 3 errors or warnings.',
162+
'Command completed with 6 errors or warnings.',
161163
'CRITICAL: msg1',
162164
'ERROR: msg2',
163165
'INFO: msg3',
@@ -181,7 +183,7 @@ def test_report_errors_does_not_report_duplicate_errors(capsys):
181183
Error(CRITICAL, 'msg1'),
182184
]
183185
severe_errors_count = cmd.report_errors(errors, quiet=True, verbose=True)
184-
assert severe_errors_count == 3
186+
assert severe_errors_count == 6
185187

186188

187189
def test_get_error_messages():
@@ -205,22 +207,6 @@ def test_get_error_messages():
205207
assert expected == emsgs
206208

207209

208-
def test_get_error_messages_quiet():
209-
errors = [
210-
Error(CRITICAL, 'msg1'),
211-
Error(ERROR, 'msg2'),
212-
Error(INFO, 'msg3'),
213-
Error(WARNING, 'msg4'),
214-
Error(DEBUG, 'msg4'),
215-
Error(NOTSET, 'msg4'),
216-
]
217-
218-
emsgs, ec = cmd.get_error_messages(errors, quiet=True)
219-
assert 3 == ec
220-
expected = []
221-
assert expected == emsgs
222-
223-
224210
def test_get_error_messages_verbose():
225211
errors = [
226212
Error(CRITICAL, 'msg1'),
@@ -232,9 +218,9 @@ def test_get_error_messages_verbose():
232218
]
233219

234220
emsgs, ec = cmd.get_error_messages(errors, verbose=True)
235-
assert 3 == ec
221+
assert 6 == ec
236222
expected = [
237-
'Command completed with 3 errors or warnings.',
223+
'Command completed with 6 errors or warnings.',
238224
'CRITICAL: msg1',
239225
'ERROR: msg2',
240226
'INFO: msg3',

tests/test_gen.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,9 @@ def test_load_inventory_with_errors(self):
103103
base_dir = get_temp_dir()
104104
errors, abouts = gen.load_inventory(location, base_dir=base_dir)
105105
expected_errors = [
106-
Error(INFO, 'Field resource is a custom field.'),
107-
Error(INFO, 'Field test is a custom field.'),
108106
Error(CRITICAL, "Field name: ['confirmed copyright'] contains illegal name characters: 0 to 9, a to z, A to Z and _. (or empty spaces) and is ignored."),
109-
Error(INFO, 'Field about_resource: Path')
107+
Error(INFO, 'Field about_resource: Path'),
108+
Error(INFO, "Field ['resource', 'test'] is a custom field.")
110109
]
111110

112111
for exp, err in zip(expected_errors, errors):
@@ -210,11 +209,12 @@ def test_generate(self):
210209
base_dir = get_temp_dir()
211210

212211
errors, abouts = gen.generate(location, base_dir)
213-
msg1 = 'Field custom1 is a custom field.'
214-
msg2 = 'Field about_resource'
212+
err_msg_list = []
213+
for severity, message in errors:
214+
err_msg_list.append(message)
215+
msg1 = "Field ['custom1'] is a custom field."
215216

216-
assert msg1 in errors[0].message
217-
assert msg2 in errors[1].message
217+
assert msg1 in err_msg_list
218218

219219
result = [a.dumps() for a in abouts][0]
220220
expected = (

tests/test_model.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -430,9 +430,9 @@ def check_About_hydrate(self, about, fields):
430430
'about_resource'])
431431

432432
expected_errors = [
433-
Error(INFO, 'Field date is a custom field.'),
434-
Error(INFO, 'Field license_spdx is a custom field.'),
435-
Error(INFO, 'Field license_text_file is a custom field.')]
433+
Error(INFO, 'Custom Field: date'),
434+
Error(INFO, 'Custom Field: license_spdx'),
435+
Error(INFO, 'Custom Field: license_text_file')]
436436

437437
errors = about.hydrate(fields)
438438

@@ -529,9 +529,10 @@ def test_About_has_errors_for_illegal_custom_field_name(self):
529529
test_file = get_test_loc('test_model/parse/illegal_custom_field.about')
530530
a = model.About(test_file)
531531
expected_errors = [
532-
Error(INFO, 'Field hydrate is a custom field.'),
532+
Error(INFO, 'Custom Field: hydrate'),
533533
Error(CRITICAL, "Internal error with custom field: 'hydrate': 'illegal name'.")
534534
]
535+
535536
assert expected_errors == a.errors
536537
assert not hasattr(getattr(a, 'hydrate'), 'value')
537538
field = list(a.custom_fields.values())[0]
@@ -753,8 +754,8 @@ def test_About_dumps_does_all_non_empty_present_fields(self):
753754
test_file = get_test_loc('test_model/parse/complete2/about.ABOUT')
754755
a = model.About(test_file)
755756
expected_error = [
756-
Error(INFO, 'Field custom1 is a custom field.'),
757-
Error(INFO, 'Field custom2 is a custom field.'),
757+
Error(INFO, 'Custom Field: custom1'),
758+
Error(INFO, 'Custom Field: custom2'),
758759
Error(INFO, 'Field custom2 is present but empty.')
759760
]
760761
assert sorted(expected_error) == sorted(a.errors)
@@ -793,8 +794,8 @@ def test_About_dumps_all_non_empty_fields(self):
793794
test_file = get_test_loc('test_model/parse/complete2/about.ABOUT')
794795
a = model.About(test_file)
795796
expected_error = [
796-
Error(INFO, 'Field custom1 is a custom field.'),
797-
Error(INFO, 'Field custom2 is a custom field.'),
797+
Error(INFO, 'Custom Field: custom1'),
798+
Error(INFO, 'Custom Field: custom2'),
798799
Error(INFO, 'Field custom2 is present but empty.')
799800
]
800801
assert sorted(expected_error) == sorted(a.errors)
@@ -842,11 +843,11 @@ def test_load_can_load_unicode(self):
842843
file_path = posixpath.join(posixpath.dirname(test_file), 'nose-selecttests-0.3.zip')
843844
err_msg = 'Field about_resource: Path %s not found' % file_path
844845
errors = [
845-
Error(INFO, 'Field dje_license is a custom field.'),
846-
Error(INFO, 'Field license_text_file is a custom field.'),
847-
Error(INFO, 'Field scm_tool is a custom field.'),
848-
Error(INFO, 'Field scm_repository is a custom field.'),
849-
Error(INFO, 'Field test is a custom field.'),
846+
Error(INFO, 'Custom Field: dje_license'),
847+
Error(INFO, 'Custom Field: license_text_file'),
848+
Error(INFO, 'Custom Field: scm_tool'),
849+
Error(INFO, 'Custom Field: scm_repository'),
850+
Error(INFO, 'Custom Field: test'),
850851
Error(INFO, err_msg)]
851852

852853
assert errors == a.errors

0 commit comments

Comments
 (0)