Skip to content

Commit db4c37b

Browse files
committed
Improve Python3 portability #280
* we still have unicode and CSV issues but only a few Signed-off-by: Philippe Ombredanne <[email protected]>
1 parent 9303ad7 commit db4c37b

File tree

9 files changed

+59
-58
lines changed

9 files changed

+59
-58
lines changed

src/attributecode/__init__.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@
1414
# limitations under the License.
1515
# ============================================================================
1616

17-
1817
from __future__ import absolute_import
1918
from __future__ import print_function
2019
from __future__ import unicode_literals
2120

2221
from collections import namedtuple
2322
import logging
2423

24+
try:
25+
basestring # Python 2
26+
except NameError:
27+
basestring = str # Python 3
28+
2529

2630
__version__ = '3.0.0.dev5'
2731

@@ -68,16 +72,16 @@ def clean_string(s):
6872
if not s:
6973
return s
7074
if s.startswith(('u"', "u'")):
71-
msg = s.lstrip('u')
72-
msg = s.replace('[u"', '["')
73-
msg = s.replace("[u'", "['")
74-
msg = s.replace("(u'", "('")
75-
msg = s.replace("(u'", "('")
76-
msg = s.replace("{u'", "{'")
77-
msg = s.replace("{u'", "{'")
78-
msg = s.replace(" u'", " '")
79-
msg = s.replace(" u'", " '")
80-
return msg
75+
s = s.lstrip('u')
76+
s = s.replace('[u"', '["')
77+
s = s.replace("[u'", "['")
78+
s = s.replace("(u'", "('")
79+
s = s.replace("(u'", "('")
80+
s = s.replace("{u'", "{'")
81+
s = s.replace("{u'", "{'")
82+
s = s.replace(" u'", " '")
83+
s = s.replace(" u'", " '")
84+
return s
8185

8286
# modeled after the logging levels
8387
CRITICAL = 50

src/attributecode/api.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@
2020

2121
from collections import namedtuple
2222
import json
23-
import urllib
23+
24+
try:
25+
from urllib import urlencode
26+
from urllib import quote
27+
except ImportError:
28+
from urllib.parse import urlencode
29+
from urllib.parse import quote
2430

2531
try:
2632
import httplib # Python 2
@@ -49,12 +55,12 @@ def build_api_url(url, api_username, api_key, license_key):
4955
payload = {'username': api_username,
5056
'api_key': api_key,
5157
'format': 'json'}
52-
encoded_payload = urllib.urlencode(payload)
58+
encoded_payload = urlencode(payload)
5359

5460
api_url = '%(url)s/%(license_key)s/?%(encoded_payload)s' % locals()
5561

5662
# handle special characters in URL such as space etc.
57-
api_url = urllib.quote(api_url, safe="%/:=&?~#+!$,;'@()*[]")
63+
api_url = quote(api_url, safe="%/:=&?~#+!$,;'@()*[]")
5864
return api_url
5965

6066

@@ -128,10 +134,10 @@ def request_license_data(url, api_key, license_key):
128134
}
129135

130136
url = url.rstrip('/')
131-
encoded_payload = urllib.urlencode(payload)
137+
encoded_payload = urlencode(payload)
132138
full_url = '%(url)s/?%(encoded_payload)s' % locals()
133139
# handle special characters in URL such as space etc.
134-
full_url = urllib.quote(full_url, safe="%/:=&?~#+!$,;'@()*[]")
140+
full_url = quote(full_url, safe="%/:=&?~#+!$,;'@()*[]")
135141
headers = {'Authorization': 'Token %s' % api_key}
136142
license_data = {}
137143
errors = []

src/attributecode/cmd.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,15 +200,13 @@ def attrib(location, output, template, mapping, inventory, quiet):
200200
if mapping:
201201
attributecode.util.have_mapping = True
202202

203-
err, abouts = model.collect_inventory(location)
204-
no_match_errors = attributecode.attrib.generate_and_save(abouts, output, mapping,
205-
template_loc=template,
206-
inventory_location=inventory)
207-
errors = []
208-
for e in err:
209-
errors.append(e)
203+
errors, abouts = model.collect_inventory(location)
204+
no_match_errors = attributecode.attrib.generate_and_save(
205+
abouts, output, mapping, template_loc=template, inventory_location=inventory)
206+
210207
for no_match_error in no_match_errors:
211208
errors.append(no_match_error)
209+
212210
log_errors(errors, quiet, os.path.dirname(output))
213211
click.echo('Finished.')
214212

src/attributecode/gen.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ def generate(location, base_dir, mapping, license_notice_text_location, fetch_li
182182
# Check if the fetch_license contains valid argument
183183
if fetch_license:
184184
# Strip the ' and " for api_url, and api_key from input
185-
api_url = fetch_license[0].strip("'").strip("\"")
186-
api_key = fetch_license[1].strip("'").strip("\"")
185+
api_url = fetch_license[0].strip("'").strip('"')
186+
api_key = fetch_license[1].strip("'").strip('"')
187187
gen_license = True
188188

189189
bdir = to_posix(base_dir)

src/attributecode/model.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,9 +1447,10 @@ def parse_license_expression(lic_expression):
14471447
return special_char, lic_list
14481448

14491449
def special_char_in_license_expresion(lic_expression):
1450-
not_support_char = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
1451-
'+', '=', '{', '}', '|', '[', ']', '\\',
1452-
':', ';', '<', '>', '?', ',', '/']
1450+
not_support_char = [
1451+
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
1452+
'+', '=', '{', '}', '|', '[', ']', '\\',
1453+
':', ';', '<', '>', '?', ',', '/']
14531454
special_character = []
14541455
for char in not_support_char:
14551456
if char in lic_expression:

src/attributecode/saneyaml.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
except NameError:
3636
unicode = str # Python 3
3737

38+
try:
39+
basestring # Python 2
40+
except NameError:
41+
basestring = str # Python 3
42+
3843

3944
"""
4045
Wrapper around PyYAML to provide sane defaults ensuring that dump/load does

src/attributecode/util.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,6 @@ def get_locations(location):
136136
a file or a directory tree containing ABOUT files.
137137
File locations are normalized using posix path separators.
138138
"""
139-
# See https://bugs.python.org/issue4071
140-
if on_windows:
141-
location = unicode(location)
142139
location = add_unc(location)
143140
location = get_absolute(location)
144141
assert os.path.exists(location)

tests/test_attrib.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ def test_generate_from_file_with_default_template(self):
5656
_errors, abouts = model.collect_inventory(test_file)
5757
result = attrib.generate_from_file(abouts)
5858
with open(get_test_loc('attrib_gen/expected_default_attrib.html')) as exp:
59-
expected = unicode(exp.read())
59+
expected = exp.read()
6060
self.assertEqual([x.rstrip() for x in expected.splitlines()],
6161
[x.rstrip() for x in result.splitlines()])

tests/test_model.py

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,16 @@ def test_PathField_check_missing_location(self):
8989
assert None == result
9090

9191
def test_TextField_loads_file(self):
92-
field = model.FileTextField(name='f', value='license.LICENSE',
93-
present=True)
92+
field = model.FileTextField(
93+
name='f', value='license.LICENSE', present=True)
9494

9595

9696
base_dir = get_test_loc('fields')
9797
errors = field.validate(base_dir=base_dir)
9898
assert [] == errors
9999

100-
expected = [('license.LICENSE', u'some license text')]
101-
result = field.value.items()
102-
assert expected == result
100+
expected = {'license.LICENSE': u'some license text'}
101+
assert expected == field.value
103102

104103
def test_UrlField_is_valid_url(self):
105104
assert model.UrlField.is_valid_url('http://www.google.com')
@@ -262,11 +261,11 @@ def test_parse_error_for_invalid_field_name(self):
262261
assert expected == result
263262

264263
expected_errors = [
265-
Error(CRITICAL, "Invalid line: 0: u'invalid space:value\\n'"),
266-
Error(CRITICAL, "Invalid line: 1: u'other-field: value\\n'"),
267-
Error(CRITICAL, "Invalid line: 4: u'_invalid_dash: value\\n'"),
268-
Error(CRITICAL, "Invalid line: 5: u'3invalid_number: value\\n'"),
269-
Error(CRITICAL, "Invalid line: 6: u'invalid.dot: value'")
264+
Error(CRITICAL, "Invalid line: 0: 'invalid space:value\\n'"),
265+
Error(CRITICAL, "Invalid line: 1: 'other-field: value\\n'"),
266+
Error(CRITICAL, "Invalid line: 4: '_invalid_dash: value\\n'"),
267+
Error(CRITICAL, "Invalid line: 5: '3invalid_number: value\\n'"),
268+
Error(CRITICAL, "Invalid line: 6: 'invalid.dot: value'")
270269
]
271270
assert expected_errors == errors
272271

@@ -289,11 +288,11 @@ def test_parse_rejects_non_ascii_names_and_accepts_unicode_values(self):
289288
errors, result = model.parse(test)
290289
expected = [(u'name', u'name'),
291290
(u'about_resource', u'.'),
292-
(u'owner', u'Mat\xedas Aguirre')]
291+
(u'owner', 'Matías Aguirre')]
293292
assert expected == result
294293

295294
expected_errors = [
296-
Error(CRITICAL, "Invalid line: 3: u'Mat\\xedas: unicode field name\\n'")]
295+
Error(CRITICAL, "Invalid line: 3: 'Matías: unicode field name\\n'")]
297296
assert expected_errors == errors
298297

299298
def test_parse_handles_blank_lines_and_spaces_in_field_names(self):
@@ -481,10 +480,8 @@ def test_About_custom_fields_are_collected_correctly_as_multiline_scalar(self):
481480
def test_About_has_errors_for_illegal_custom_field_name(self):
482481
test_file = get_test_loc('parse/illegal_custom_field.about')
483482
a = model.About(test_file)
484-
result = a.custom_fields.items()
485-
expected = [
486-
]
487-
assert expected == result
483+
result = a.custom_fields
484+
assert {} == result
488485

489486
def test_About_file_fields_are_empty_if_present_and_path_missing(self):
490487
test_file = get_test_loc('parse/missing_notice_license_files.ABOUT')
@@ -496,19 +493,12 @@ def test_About_file_fields_are_empty_if_present_and_path_missing(self):
496493
err_msg1 = u'Field license_file: Path %s not found' % file_path1
497494
err_msg2 = u'Field notice_file: Path %s not found' % file_path2
498495

499-
expected_errors = [
500-
err_msg1, err_msg2
501-
]
502-
496+
expected_errors = [err_msg1, err_msg2]
503497
errors = model.check_file_field_exist(a, test_file)
504498
assert expected_errors == errors
505-
expected = [(u'test.LICENSE', None)]
506-
result = a.license_file.value.items()
507-
assert expected == result
508499

509-
expected = [(u'test.NOTICE', None)]
510-
result = a.notice_file.value.items()
511-
assert expected == result
500+
assert {'test.LICENSE': None} == a.license_file.value
501+
assert {'test.NOTICE': None} == a.notice_file.value
512502

513503
def test_About_notice_and_license_text_are_loaded_from_file(self):
514504
test_file = get_test_loc('parse/license_file_notice_file.ABOUT')

0 commit comments

Comments
 (0)