Skip to content

Commit 9a9d735

Browse files
committed
Fixed #451
* Add support for '@' as filename * Update SPEC * Add tests * improve efficiency
1 parent 124ab93 commit 9a9d735

File tree

4 files changed

+75
-52
lines changed

4 files changed

+75
-52
lines changed

SPECIFICATION.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ABOUT File Specification v3.2.0
1+
ABOUT File Specification v3.2.1
22

33

44
Purpose
@@ -74,7 +74,7 @@ A file name can contain only these US-ASCII characters:
7474

7575
- digits from 0 to 9
7676
- uppercase and lowercase letters from A to Z
77-
- the following symbols: "_", "-", "+", ".", "(", ")", "~", "[", "]", "{", "}"
77+
- the following symbols: "_", "-", "+", ".", "(", ")", "~", "[", "]", "{", "}", "@"
7878

7979
- The case of a file name is not significant. On case-sensitive file systems
8080
(such as on Linux), a tool must report an error if two ABOUT files stored in

src/attributecode/gen.py

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from attributecode.util import add_unc
3838
from attributecode.util import csv
3939
from attributecode.util import file_fields
40+
from attributecode.util import invalid_chars
4041
from attributecode.util import to_posix
4142
from attributecode.util import UNC_PREFIX_POSIX
4243
from attributecode.util import unique
@@ -77,42 +78,42 @@ def check_duplicated_columns(location):
7778
errors.append(Error(ERROR, msg))
7879
return unique(errors)
7980

80-
81-
def check_duplicated_about_resource(inventory_dict):
81+
def check_duplicated_about_resource(arp, arp_list):
8282
"""
8383
Return a list of errors for duplicated about_resource in a CSV file at location.
8484
"""
85-
arp_list = []
86-
errors = []
87-
for component in inventory_dict:
88-
# Ignore all the empty path
89-
if component['about_resource']:
90-
if component['about_resource'] in arp_list:
91-
msg = ("The input has duplicated values in 'about_resource' "
92-
"field: " + component['about_resource'])
93-
errors.append(Error(CRITICAL, msg))
94-
else:
95-
arp_list.append(component['about_resource'])
96-
return errors
85+
if arp in arp_list:
86+
msg = ("The input has duplicated values in 'about_resource' "
87+
"field: " + arp)
88+
return Error(CRITICAL, msg)
89+
return ''
9790

98-
99-
def check_newline_in_file_field(inventory_dict):
91+
def check_newline_in_file_field(component):
10092
"""
10193
Return a list of errors for newline characters detected in *_file fields.
10294
"""
10395
errors = []
104-
for component in inventory_dict:
105-
for k in component.keys():
106-
if k in file_fields:
107-
try:
108-
if '\n' in component[k]:
109-
msg = ("New line character detected in '%s' for '%s' which is not supported."
110-
"\nPlease use ',' to declare multiple files.") % (k, component['about_resource'])
111-
errors.append(Error(CRITICAL, msg))
112-
except:
113-
pass
96+
for k in component.keys():
97+
if k in file_fields:
98+
try:
99+
if '\n' in component[k]:
100+
msg = ("New line character detected in '%s' for '%s' which is not supported."
101+
"\nPlease use ',' to declare multiple files.") % (k, component['about_resource'])
102+
errors.append(Error(CRITICAL, msg))
103+
except:
104+
pass
114105
return errors
115106

107+
def check_about_resource_filename(arp):
108+
"""
109+
Return error for invalid/non-support about_resource's filename or
110+
empty string if no error is found.
111+
"""
112+
if invalid_chars(arp):
113+
msg = ("Invalid characters present in 'about_resource' "
114+
"field: " + arp)
115+
return (Error(CRITICAL, msg))
116+
return ''
116117

117118
# TODO: this should be either the CSV or the ABOUT files but not both???
118119
def load_inventory(location, base_dir, reference_dir=None):
@@ -139,15 +140,26 @@ def load_inventory(location, base_dir, reference_dir=None):
139140
inventory = util.load_json(location)
140141

141142
try:
142-
# FIXME: this should not be done here.
143-
dup_about_resource_err = check_duplicated_about_resource(inventory)
144-
if dup_about_resource_err:
145-
errors.extend(dup_about_resource_err)
146-
return errors, abouts
147-
newline_in_file = check_newline_in_file_field(inventory)
148-
if newline_in_file:
149-
errors.extend(newline_in_file)
143+
arp_list = []
144+
errors = []
145+
for component in inventory:
146+
arp = component['about_resource']
147+
dup_err = check_duplicated_about_resource(arp, arp_list)
148+
if dup_err:
149+
errors.append(dup_err)
150+
else:
151+
arp_list.append(arp)
152+
153+
newline_in_file_err = check_newline_in_file_field(component)
154+
for err in newline_in_file_err:
155+
errors.append(err)
156+
157+
invalid_about_filename = check_about_resource_filename(arp)
158+
if invalid_about_filename:
159+
errors.append(invalid_about_filename)
160+
if errors:
150161
return errors, abouts
162+
151163
except Exception as e:
152164
# TODO: why catch ALL Exception
153165
msg = "The essential field 'about_resource' is not found in the <input>"

src/attributecode/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def to_posix(path):
7070
UNC_PREFIX_POSIX = to_posix(UNC_PREFIX)
7171
UNC_PREFIXES = (UNC_PREFIX_POSIX, UNC_PREFIX,)
7272

73-
valid_file_chars = string.digits + string.ascii_letters + '_-.+()~[]{}|' + ' '
73+
valid_file_chars = string.digits + string.ascii_letters + '_-.+()~[]{}|@' + ' '
7474

7575

7676
def invalid_chars(path):

tests/test_gen.py

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,27 +46,38 @@ def test_check_duplicated_columns_handles_lower_upper_case(self):
4646
assert expected == result
4747

4848
def test_check_duplicated_about_resource(self):
49-
test_dict = [
50-
{'about_resource': '/test/test.c', 'version': '1.03', 'name': 'test.c'},
51-
{'about_resource': '/test/abc/', 'version': '1.0', 'name': 'abc'},
52-
{'about_resource': '/test/test.c', 'version': '1.04', 'name': 'test1.c'}]
53-
expected = [
54-
Error(CRITICAL,
55-
"The input has duplicated values in 'about_resource' field: /test/test.c")]
56-
result = gen.check_duplicated_about_resource(test_dict)
57-
assert expected == result
49+
arp_list = ['/test/test.c', 'test/test1.h']
50+
arp1 = '/test/test.c'
51+
arp2 = '/test/tmp/test.c'
52+
expected = Error(CRITICAL,
53+
"The input has duplicated values in 'about_resource' field: " + arp1)
54+
result1 = gen.check_duplicated_about_resource(arp1, arp_list)
55+
result2 = gen.check_duplicated_about_resource(arp2, arp_list)
56+
assert result1 == expected
57+
assert result2 == ''
5858

5959
def test_check_newline_in_file_field(self):
60-
test_dict = [
61-
{'about_resource': '/test/test.c', 'name': 'test.c', 'notice_file': 'NOTICE\nNOTICE2'},
62-
{'about_resource': '/test/abc/', 'version': '1.0', 'name': 'abc'},
63-
{'about_resource': '/test/test.c', 'version': '1.04', 'name': 'test1.c'}]
60+
test_dict1 = {'about_resource': '/test/test.c', 'name': 'test.c', 'notice_file': 'NOTICE\nNOTICE2'}
61+
test_dict2 = {'about_resource': '/test/test.c', 'name': 'test.c', 'notice_file': 'NOTICE, NOTICE2'}
6462
expected = [
6563
Error(CRITICAL,
6664
"New line character detected in 'notice_file' for '/test/test.c' which is not supported."
6765
"\nPlease use ',' to declare multiple files.")]
68-
result = gen.check_newline_in_file_field(test_dict)
69-
assert expected == result
66+
result1 = gen.check_newline_in_file_field(test_dict1)
67+
result2 = gen.check_newline_in_file_field(test_dict2)
68+
assert result1 == expected
69+
assert result2 == []
70+
71+
def test_check_about_resource_filename(self):
72+
arp1 = '/test/[email protected]'
73+
arp2 = '/test/t!est.c'
74+
msg = ("Invalid characters present in 'about_resource' "
75+
"field: " + arp2)
76+
expected2 = Error(CRITICAL, msg)
77+
result1 = gen.check_about_resource_filename(arp1)
78+
result2 = gen.check_about_resource_filename(arp2)
79+
assert result1 == ''
80+
assert result2 == expected2
7081

7182
def test_load_inventory(self):
7283
location = get_test_loc('test_gen/inv.csv')

0 commit comments

Comments
 (0)