Added support for Python3000

This commit is contained in:
Matt Clarkson 2013-10-17 09:36:32 +01:00 committed by Matt Clarkson
parent d4f3c9cf1b
commit b511d7da0e
2 changed files with 69 additions and 16 deletions

40
cpplint/cpplint.py vendored
View File

@ -52,6 +52,21 @@ import string
import sys import sys
import unicodedata import unicodedata
Py3k = (sys.version_info[0] == 3)
"""A boolean to check if we are running Python3000"""
try:
xrange(0,1)
except NameError:
xrange = range
try:
unicode
except NameError:
basestring = unicode = str
try:
long
except NameError:
long = int
_USAGE = """ _USAGE = """
Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
@ -840,7 +855,11 @@ class _CppLintState(object):
def PrintErrorCounts(self): def PrintErrorCounts(self):
"""Print a summary of errors by category, and the total.""" """Print a summary of errors by category, and the total."""
for category, count in self.errors_by_category.iteritems(): try:
items = self.errors_by_category.iteritems()
except AttributeError:
items = self.errors_by_category.items()
for category, count in items:
sys.stderr.write('Category \'%s\' errors found: %d\n' % sys.stderr.write('Category \'%s\' errors found: %d\n' %
(category, count)) (category, count))
sys.stderr.write('Total errors found: %d\n' % self.error_count) sys.stderr.write('Total errors found: %d\n' % self.error_count)
@ -1815,7 +1834,7 @@ def CheckForBadCharacters(filename, lines, error):
error: The function to call with any errors found. error: The function to call with any errors found.
""" """
for linenum, line in enumerate(lines): for linenum, line in enumerate(lines):
if u'\ufffd' in line: if unicode(b'\xef\xbf\xbd', 'utf-8') in line:
error(filename, linenum, 'readability/utf8', 5, error(filename, linenum, 'readability/utf8', 5,
'Line contains invalid UTF-8 (or Unicode replacement character).') 'Line contains invalid UTF-8 (or Unicode replacement character).')
if '\0' in line: if '\0' in line:
@ -4701,7 +4720,10 @@ def _GetTextInside(text, start_pattern):
# Give opening punctuations to get the matching close-punctuations. # Give opening punctuations to get the matching close-punctuations.
matching_punctuation = {'(': ')', '{': '}', '[': ']'} matching_punctuation = {'(': ')', '{': '}', '[': ']'}
closing_punctuation = set(matching_punctuation.itervalues()) try:
closing_punctuation = set(matching_punctuation.values())
except AttributeError:
closing_punctuation = set(matching_punctuation.itervalues())
# Find the position to start extracting text. # Find the position to start extracting text.
match = re.search(start_pattern, text, re.M) match = re.search(start_pattern, text, re.M)
@ -5671,7 +5693,7 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
# include_dict is modified during iteration, so we iterate over a copy of # include_dict is modified during iteration, so we iterate over a copy of
# the keys. # the keys.
header_keys = include_dict.keys() header_keys = list(include_dict.keys())
for header in header_keys: for header in header_keys:
(same_module, common_path) = FilesBelongToSameModule(abs_filename, header) (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
fullpath = common_path + header fullpath = common_path + header
@ -6306,10 +6328,11 @@ def main():
# Change stderr to write with replacement characters so we don't die # Change stderr to write with replacement characters so we don't die
# if we try to print something containing non-ASCII characters. # if we try to print something containing non-ASCII characters.
sys.stderr = codecs.StreamReaderWriter(sys.stderr, if not Py3k:
codecs.getreader('utf8'), sys.stderr = codecs.StreamReaderWriter(sys.stderr,
codecs.getwriter('utf8'), codecs.getreader('utf8'),
'replace') codecs.getwriter('utf8'),
'replace')
_cpplint_state.ResetErrorCounts() _cpplint_state.ResetErrorCounts()
for filename in filenames: for filename in filenames:
@ -6321,3 +6344,4 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -41,7 +41,26 @@ import sys
import unittest import unittest
import cpplint import cpplint
import sys
try:
xrange(0,1)
except NameError:
xrange = range
try:
unicode
except NameError:
basestring = unicode = str
try:
long
except NameError:
long = int
Py3k = (sys.version_info[0] == 3)
if Py3k:
chrstr = bytes
else:
def chrstr(l):
return ''.join([chr(x) for x in l])
# This class works as an error collector and replaces cpplint.Error # This class works as an error collector and replaces cpplint.Error
# function for the unit tests. We also verify each category we see # function for the unit tests. We also verify each category we see
@ -305,8 +324,11 @@ class CpplintTest(CpplintTestBase):
# Test get line width. # Test get line width.
def testGetLineWidth(self): def testGetLineWidth(self):
self.assertEquals(0, cpplint.GetLineWidth('')) self.assertEquals(0, cpplint.GetLineWidth(''))
self.assertEquals(10, cpplint.GetLineWidth(u'x' * 10)) self.assertEquals(10, cpplint.GetLineWidth(unicode('x') * 10))
self.assertEquals(16, cpplint.GetLineWidth(u'都|道|府|県|支庁')) try:
self.assertEquals(16, cpplint.GetLineWidth('都|道|府|県|支庁'.decode('utf-8')))
except AttributeError:
self.assertEquals(16, cpplint.GetLineWidth('都|道|府|県|支庁'))
def testGetTextInside(self): def testGetTextInside(self):
self.assertEquals('', cpplint._GetTextInside('fun()', r'fun\(')) self.assertEquals('', cpplint._GetTextInside('fun()', r'fun\('))
@ -2928,7 +2950,7 @@ class CpplintTest(CpplintTestBase):
error_collector = ErrorCollector(self.assert_) error_collector = ErrorCollector(self.assert_)
cpplint.ProcessFileData( cpplint.ProcessFileData(
'foo.cc', 'cc', 'foo.cc', 'cc',
unicode(raw_bytes, 'utf8', 'replace').split('\n'), raw_bytes.decode('utf-8', 'replace').split('\n'),
error_collector) error_collector)
# The warning appears only once. # The warning appears only once.
self.assertEquals( self.assertEquals(
@ -2938,12 +2960,19 @@ class CpplintTest(CpplintTestBase):
' (or Unicode replacement character).' ' (or Unicode replacement character).'
' [readability/utf8] [5]')) ' [readability/utf8] [5]'))
DoTest(self, 'Hello world\n', False) # For Python 2/3 compatibility we must use the chrstr shim to create the
DoTest(self, '\xe9\x8e\xbd\n', False) # the byte strings because Python3 automatically trys to encode it to
DoTest(self, '\xe9x\x8e\xbd\n', True) # UTF-8. Normal strings must be encoded to ascii to make the DoTest
# function correctly work on Python3
DoTest(self, 'Hello world\n'.encode('ascii'), False)
# '\xe9 \x8e \xbd \n'
DoTest(self, chrstr([233, 142, 189, 10]), False)
# '\xe9 x \x8e \xbd \n'
DoTest(self, chrstr([233, 120, 142, 189, 10]), True)
# This is the encoding of the replacement character itself (which # This is the encoding of the replacement character itself (which
# you can see by evaluating codecs.getencoder('utf8')(u'\ufffd')). # you can see by evaluating codecs.getencoder('utf8')(u'\ufffd')).
DoTest(self, '\xef\xbf\xbd\n', True) # '\xef \xbf \xbd \n'
DoTest(self, chrstr([239, 191, 189, 10]), True)
def testBadCharacters(self): def testBadCharacters(self):
# Test for NUL bytes only # Test for NUL bytes only
@ -2961,7 +2990,7 @@ class CpplintTest(CpplintTestBase):
cpplint.ProcessFileData( cpplint.ProcessFileData(
'nul_utf8.cc', 'cc', 'nul_utf8.cc', 'cc',
['// Copyright 2014 Your Company.', ['// Copyright 2014 Your Company.',
unicode('\xe9x\0', 'utf8', 'replace'), ''], chrstr([233, 120, 0]).decode('utf-8', 'replace'), ''],
error_collector) error_collector)
self.assertEquals( self.assertEquals(
error_collector.Results(), error_collector.Results(),