Repository: cpplint/cpplint

Issue:
--exclude not work on Windows with cpplint 1.4.4 Python 3.7.3
I'm trying to use cpplint for code static analysis and here I'm in the trouble with excluded directories :(

Long time ago I used a batch script to list all directory and files into a file list and feed cpplint to get the results, but there's distadvantages that when the files it too many it'll overflow the max length of command line to work.

I've already try to use all the follow code, but none works:

```
cpplint --root=src --filter=-build/include_subdir,-build/c++11 --repository=src --recursive  --exclude=src/third_party/* src
```

```
cpplint --root=src --filter=-build/include_subdir,-build/c++11 --repository=src --recursive  --exclude=src/third_party/*/* src
```

```
cpplint --root=src --filter=-build/include_subdir,-build/c++11 --repository=src --recursive  --exclude=src/third_party/*/* --exclude=src/third_party/* --exclude=src/third_party/*/*/* src
```

cpplint always lint the very `src/third_party` directory, please help me, I'm struggling with this issue about several weeks. Hopeless :(

Remark:

cpplint is installed by:

```
pip install cpplint
```

Discussion:

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a161699..77ca865 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,21 +1,19 @@
 name: Test
-
-on: [push, pull_request_target]
-
+on: [push, pull_request]
 jobs:
   build-test:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        python-version: ['3.7', '3.8', '3.9', 'pypy-3.9']
+        python-version: ['3.9', 'pypy3.10', '3.11']
 
     steps:
       - name: Checkout
-        uses: actions/checkout@v2
+        uses: actions/checkout@v4
         with:
           fetch-depth: 0
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v2
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python-version }}
           architecture: x64
@@ -24,8 +22,6 @@ jobs:
       - name: Install dependencies
         run: |
           python -m pip install --upgrade pip
-          python -m pip install --upgrade setuptools
           python -m pip install -e .[dev]
-          python -m pip install "tox<4.0.0" "tox-gh-actions<3.0.0"
       - name: Test with tox
         run: tox
diff --git a/.pylintrc b/.pylintrc
index 7f98f10..549279a 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -1,7 +1,7 @@
 [BASIC]
 include-naming-hint=yes
-method-rgx=[A-Z_][A-Za-z0-9]{2,49}$
-function-rgx=[A-Z_][A-Za-z0-9]{2,49}$|main|unicode_escape_decode
+method-rgx=[A-Z_][A-Za-z0-9]{2,49}$|__init__
+function-rgx=[A-Z_][A-Za-z0-9]{2,49}$|main
 const-rgx=[a-zA-Z_][A-Za-z0-9_]{2,49}$
 variable-rgx=[a-z_][a-z0-9_]{0,49}$
 argument-rgx=[a-z_][a-z0-9_]{0,49}$
diff --git a/cpplint.py b/cpplint.py
index 2b9ca31..dadd142 100755
--- a/cpplint.py
+++ b/cpplint.py
@@ -41,11 +41,6 @@ We do a small hack, which is to ignore //'s with "'s after them on the
 same line, but it is far from perfect (in either direction).
 """
 
-# cpplint predates fstrings
-# pylint: disable=consider-using-f-string
-
-# pylint: disable=invalid-name
-
 import codecs
 import copy
 import getopt
@@ -54,7 +49,6 @@ import itertools
 import math  # for log
 import os
 import re
-import sre_compile
 import string
 import sys
 import sysconfig
@@ -64,15 +58,7 @@ import xml.etree.ElementTree
 # if empty, use defaults
 _valid_extensions = set([])
 
-__VERSION__ = '1.6.1'
-
-try:
-  #  -- pylint: disable=used-before-assignment
-  xrange          # Python 2
-except NameError:
-  #  -- pylint: disable=redefined-builtin
-  xrange = range  # Python 3
-
+__VERSION__ = '1.7.0'
 
 _USAGE = """
 Syntax: cpplint.py [--verbose=#] [--output=emacs|eclipse|vs7|junit|sed|gsed]
@@ -98,9 +84,10 @@ Syntax: cpplint.py [--verbose=#] [--output=emacs|eclipse|vs7|junit|sed|gsed]
   certain of the problem, and 1 meaning it could be a legitimate construct.
   This will miss some errors, and is not a substitute for a code review.
 
-  To suppress false-positive errors of a certain category, add a
-  'NOLINT(category)' comment to the line.  NOLINT or NOLINT(*)
-  suppresses errors of all categories on that line.
+  To suppress false-positive errors of certain categories, add a
+  'NOLINT(category[, category...])' comment to the line.  NOLINT or NOLINT(*)
+  suppresses errors of all categories on that line. To suppress categories
+  on the next line use NOLINTNEXTLINE instead of NOLINT.
 
   The files passed in will be linted; at least one file must be provided.
   Default linted extensions are %s.
@@ -408,7 +395,7 @@ _CPP_HEADERS = frozenset([
     'alloc.h',
     'builtinbuf.h',
     'bvector.h',
-    'complex.h',
+    # 'complex.h', collides with System C header "complex.h" since C11
     'defalloc.h',
     'deque.h',
     'editbuf.h',
@@ -454,7 +441,7 @@ _CPP_HEADERS = frozenset([
     'tree.h',
     'type_traits.h',
     'vector.h',
-    # 17.6.1.2 C++ library headers
+    # C++ library headers
     'algorithm',
     'array',
     'atomic',
@@ -508,9 +495,9 @@ _CPP_HEADERS = frozenset([
     'utility',
     'valarray',
     'vector',
-    # 17.6.1.2 C++14 headers
+    # C++14 headers
     'shared_mutex',
-    # 17.6.1.2 C++17 headers
+    # C++17 headers
     'any',
     'charconv',
     'codecvt',
@@ -520,7 +507,33 @@ _CPP_HEADERS = frozenset([
     'optional',
     'string_view',
     'variant',
-    # 17.6.1.2 C++ headers for C library facilities
+    # C++20 headers
+    'barrier',
+    'bit',
+    'compare',
+    'concepts',
+    'coroutine',
+    'format',
+    'latch'
+    'numbers',
+    'ranges',
+    'semaphore',
+    'source_location',
+    'span',
+    'stop_token',
+    'syncstream',
+    'version',
+    # C++23 headers
+    'expected',
+    'flat_map',
+    'flat_set',
+    'generator',
+    'mdspan',
+    'print',
+    'spanstream',
+    'stacktrace',
+    'stdfloat',
+    # C++ headers for C library facilities
     'cassert',
     'ccomplex',
     'cctype',
@@ -581,6 +594,9 @@ _C_HEADERS = frozenset([
     'uchar.h',
     'wchar.h',
     'wctype.h',
+    # C23 headers
+    'stdbit.h',
+    'stdckdint.h',
     # additional POSIX C headers
     'aio.h',
     'arpa/inet.h',
@@ -772,16 +788,16 @@ _CHECK_REPLACEMENT = dict([(macro_var, {}) for macro_var in _CHECK_MACROS])
 for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
                         ('>=', 'GE'), ('>', 'GT'),
                         ('<=', 'LE'), ('<', 'LT')]:
-  _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
-  _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
-  _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
-  _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
+  _CHECK_REPLACEMENT['DCHECK'][op] = f'DCHECK_{replacement}'
+  _CHECK_REPLACEMENT['CHECK'][op] = f'CHECK_{replacement}'
+  _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = f'EXPECT_{replacement}'
+  _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = f'ASSERT_{replacement}'
 
 for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
                             ('>=', 'LT'), ('>', 'LE'),
                             ('<=', 'GT'), ('<', 'GE')]:
-  _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
-  _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
+  _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = f'EXPECT_{inv_replacement}'
+  _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = f'ASSERT_{inv_replacement}'
 
 # Alternative tokens and their replacements.  For full list, see section 2.5
 # Alternative tokens [lex.digraph] in the C++ standard.
@@ -808,7 +824,7 @@ _ALT_TOKEN_REPLACEMENT = {
 # False positives include C-style multi-line comments and multi-line strings
 # but those have always been troublesome for cpplint.
 _ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
-    r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)')
+    r'([ =()])(' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')([ (]|$)')
 
 
 # These constants define types of headers for use with
@@ -854,8 +870,6 @@ _SED_FIXUPS = {
   'Missing space after ,': r's/,\([^ ]\)/, \1/g',
 }
 
-_regexp_compile_cache = {}
-
 # {str, set(int)}: a map from error categories to sets of linenumbers
 # on which those errors are expected and should be suppressed.
 _error_suppressions = {}
@@ -883,36 +897,6 @@ _line_length = 80
 # This allows to use different include order rule than default
 _include_order = "default"
 
-try:
-  #  -- pylint: disable=used-before-assignment
-  unicode
-except NameError:
-  #  -- pylint: disable=redefined-builtin
-  basestring = unicode = str
-
-try:
-  #  -- pylint: disable=used-before-assignment
-  long
-except NameError:
-  #  -- pylint: disable=redefined-builtin
-  long = int
-
-if sys.version_info < (3,):
-  #  -- pylint: disable=no-member
-  # BINARY_TYPE = str
-  itervalues = dict.itervalues
-  iteritems = dict.iteritems
-else:
-  # BINARY_TYPE = bytes
-  itervalues = dict.values
-  iteritems = dict.items
-
-def unicode_escape_decode(x):
-  if sys.version_info < (3,):
-    return codecs.unicode_escape_decode(x)[0]
-  else:
-    return x
-
 # Treat all headers starting with 'h' equally: .h, .hpp, .hxx etc.
 # This is set by --headers flag.
 _hpp_headers = set([])
@@ -961,7 +945,7 @@ def ProcessExtensionsOption(val):
   except ValueError:
     PrintUsage('Extensions should be a comma-separated list of values;'
                'for example: extensions=hpp,cpp\n'
-               'This could not be parsed: "%s"' % (val,))
+              f'This could not be parsed: "{val}"')
 
 def GetNonHeaderExtensions():
   return GetAllExtensions().difference(GetHeaderExtensions())
@@ -979,18 +963,17 @@ def ParseNolintSuppressions(filename, raw_line, linenum, error):
     linenum: int, the number of the current line.
     error: function, an error handler.
   """
-  matched = Search(r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
+  matched = re.search(r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
   if matched:
     if matched.group(1):
       suppressed_line = linenum + 1
     else:
       suppressed_line = linenum
-    category = matched.group(2)
-    if category in (None, '(*)'):  # => "suppress all"
+    categories = matched.group(2)
+    if categories in (None, '(*)'):  # => "suppress all"
       _error_suppressions.setdefault(None, set()).add(suppressed_line)
-    else:
-      if category.startswith('(') and category.endswith(')'):
-        category = category[1:-1]
+    elif categories.startswith('(') and categories.endswith(')'):
+      for category in set(map(lambda c: c.strip(), categories[1:-1].split(','))):
         if category in _ERROR_CATEGORIES:
           _error_suppressions.setdefault(category, set()).add(suppressed_line)
         elif any(c for c in _OTHER_NOLINT_CATEGORY_PREFIXES if category.startswith(c)):
@@ -998,7 +981,7 @@ def ParseNolintSuppressions(filename, raw_line, linenum, error):
           pass
         elif category not in _LEGACY_ERROR_CATEGORIES:
           error(filename, linenum, 'readability/nolint', 5,
-                'Unknown NOLINT error category: %s' % category)
+                f'Unknown NOLINT error category: {category}')
 
 
 def ProcessGlobalSuppresions(lines):
@@ -1043,41 +1026,6 @@ def IsErrorSuppressedByNolint(category, linenum):
           linenum in _error_suppressions.get(None, set()))
 
 
-def Match(pattern, s):
-  """Matches the string with the pattern, caching the compiled regexp."""
-  # The regexp compilation caching is inlined in both Match and Search for
-  # performance reasons; factoring it out into a separate function turns out
-  # to be noticeably expensive.
-  if pattern not in _regexp_compile_cache:
-    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
-  return _regexp_compile_cache[pattern].match(s)
-
-
-def ReplaceAll(pattern, rep, s):
-  """Replaces instances of pattern in a string with a replacement.
-
-  The compiled regex is kept in a cache shared by Match and Search.
-
-  Args:
-    pattern: regex pattern
-    rep: replacement text
-    s: search string
-
-  Returns:
-    string with replacements made (or original string if no replacements)
-  """
-  if pattern not in _regexp_compile_cache:
-    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
-  return _regexp_compile_cache[pattern].sub(rep, s)
-
-
-def Search(pattern, s):
-  """Searches the string for the pattern, caching the compiled regexp."""
-  if pattern not in _regexp_compile_cache:
-    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
-  return _regexp_compile_cache[pattern].search(s)
-
-
 def _IsSourceExtension(s):
   """File extension (excluding dot) matches a source file extension."""
   return s in GetNonHeaderExtensions()
@@ -1195,7 +1143,7 @@ class _IncludeState(object):
     # If previous line was a blank line, assume that the headers are
     # intentionally sorted the way they are.
     if (self._last_header > header_path and
-        Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
+        re.match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
       return False
     return True
 
@@ -1213,9 +1161,8 @@ class _IncludeState(object):
       error message describing what's wrong.
 
     """
-    error_message = ('Found %s after %s' %
-                     (self._TYPE_NAMES[header_type],
-                      self._SECTION_NAMES[self._section]))
+    error_message = (f'Found {self._TYPE_NAMES[header_type]}'
+                     f' after {self._SECTION_NAMES[self._section]}')
 
     last_section = self._section
 
@@ -1334,7 +1281,7 @@ class _CppLintState(object):
     for filt in self.filters:
       if not (filt.startswith('+') or filt.startswith('-')):
         raise ValueError('Every filter in --filters must start with + or -'
-                         ' (%s does not)' % filt)
+                        f' ({filt} does not)')
 
   def BackupFilters(self):
     """ Saves the current filter list to backup storage."""
@@ -1361,11 +1308,10 @@ class _CppLintState(object):
 
   def PrintErrorCounts(self):
     """Print a summary of errors by category, and the total."""
-    for category, count in sorted(iteritems(self.errors_by_category)):
-      self.PrintInfo('Category \'%s\' errors found: %d\n' %
-                       (category, count))
+    for category, count in sorted(dict.items(self.errors_by_category)):
+      self.PrintInfo(f'Category \'{category}\' errors found: {count}\n')
     if self.error_count > 0:
-      self.PrintInfo('Total errors found: %d\n' % self.error_count)
+      self.PrintInfo(f'Total errors found: {self.error_count}\n')
 
   def PrintInfo(self, message):
     # _quiet does not represent --quiet flag.
@@ -1537,7 +1483,7 @@ class _FunctionState(object):
     if not self.in_a_function:
       return
 
-    if Match(r'T(EST|est)', self.current_function):
+    if re.match(r'T(EST|est)', self.current_function):
       base_trigger = self._TEST_TRIGGER
     else:
       base_trigger = self._NORMAL_TRIGGER
@@ -1550,9 +1496,8 @@ class _FunctionState(object):
         error_level = 5
       error(filename, linenum, 'readability/fn_size', error_level,
             'Small and focused functions are preferred:'
-            ' %s has %d non-comment lines'
-            ' (error triggered by exceeding %d lines).'  % (
-                self.current_function, self.lines_in_function, trigger))
+            f' {self.current_function} has {self.lines_in_function} non-comment lines'
+            f' (error triggered by exceeding {trigger} lines).')
 
   def End(self):
     """Stop analyzing function body."""
@@ -1723,26 +1668,27 @@ def Error(filename, linenum, category, confidence, message):
   if _ShouldPrintError(category, confidence, linenum):
     _cpplint_state.IncrementErrorCount(category)
     if _cpplint_state.output_format == 'vs7':
-      _cpplint_state.PrintError('%s(%s): error cpplint: [%s] %s [%d]\n' % (
-          filename, linenum, category, message, confidence))
+      _cpplint_state.PrintError(f'{filename}({linenum}): error cpplint:'
+                                f' [{category}] {message} [{confidence}]\n')
     elif _cpplint_state.output_format == 'eclipse':
-      sys.stderr.write('%s:%s: warning: %s  [%s] [%d]\n' % (
-          filename, linenum, message, category, confidence))
+      sys.stderr.write(f'{filename}:{linenum}: warning:'
+                       f' {message}  [{category}] [{confidence}]\n')
     elif _cpplint_state.output_format == 'junit':
-      _cpplint_state.AddJUnitFailure(filename, linenum, message, category,
-          confidence)
+      _cpplint_state.AddJUnitFailure(filename, linenum, message, category, confidence)
     elif _cpplint_state.output_format in ['sed', 'gsed']:
       if message in _SED_FIXUPS:
-        sys.stdout.write(_cpplint_state.output_format + " -i '%s%s' %s # %s  [%s] [%d]\n" % (
-            linenum, _SED_FIXUPS[message], filename, message, category, confidence))
+        sys.stdout.write(f"{_cpplint_state.output_format} -i"
+                         f" '{linenum}{_SED_FIXUPS[message]}' {filename}"
+                         f" # {message}  [{category}] [{confidence}]\n")
       else:
-        sys.stderr.write('# %s:%s:  "%s"  [%s] [%d]\n' % (
-            filename, linenum, message, category, confidence))
+        sys.stderr.write(f'# {filename}:{linenum}: '
+                         f' "{message}"  [{category}] [{confidence}]\n')
     else:
-      final_message = '%s:%s:  %s  [%s] [%d]\n' % (
-          filename, linenum, message, category, confidence)
+      final_message = (f'{filename}:{linenum}: '
+                       f' {message}  [{category}] [{confidence}]\n')
       sys.stderr.write(final_message)
 
+
 # Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard.
 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
     r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
@@ -1810,7 +1756,7 @@ def CleanseRawStrings(raw_lines):
         # Found the end of the string, match leading space for this
         # line and resume copying the original lines, and also insert
         # a "" on the last line.
-        leading_space = Match(r'^(\s*)\S', line)
+        leading_space = re.match(r'^(\s*)\S', line)
         line = leading_space.group(1) + '""' + line[end + len(delimiter):]
         delimiter = None
       else:
@@ -1831,9 +1777,9 @@ def CleanseRawStrings(raw_lines):
       # before removing raw strings.  This is because there are some
       # cpplint checks that requires the comments to be preserved, but
       # we don't want to check comments that are inside raw strings.
-      matched = Match(r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
+      matched = re.match(r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
       if (matched and
-          not Match(r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//',
+          not re.match(r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//',
                     matched.group(1))):
         delimiter = ')' + matched.group(2) + '"'
 
@@ -1916,6 +1862,28 @@ def CleanseComments(line):
   return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
 
 
+def ReplaceAlternateTokens(line):
+  """Replace any alternate token by its original counterpart.
+
+  In order to comply with the google rule stating that unary operators should
+  never be followed by a space, an exception is made for the 'not' and 'compl'
+  alternate tokens. For these, any trailing space is removed during the
+  conversion.
+
+  Args:
+    line: The line being processed.
+
+  Returns:
+    The line with alternate tokens replaced.
+  """
+  for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
+    token = _ALT_TOKEN_REPLACEMENT[match.group(2)]
+    tail = '' if match.group(2) in ['not', 'compl'] and match.group(3) == ' ' \
+           else r'\3'
+    line = re.sub(match.re, rf'\1{token}{tail}', line, count=1)
+  return line
+
+
 class CleansedLines(object):
   """Holds 4 copies of all lines with different preprocessing applied to them.
 
@@ -1928,16 +1896,17 @@ class CleansedLines(object):
   """
 
   def __init__(self, lines):
+    if '-readability/alt_tokens' in _cpplint_state.filters:
+      for i, line in enumerate(lines):
+        lines[i] = ReplaceAlternateTokens(line)
     self.elided = []
     self.lines = []
     self.raw_lines = lines
     self.num_lines = len(lines)
     self.lines_without_raw_strings = CleanseRawStrings(lines)
-    # # pylint: disable=consider-using-enumerate
-    for linenum in range(len(self.lines_without_raw_strings)):
-      self.lines.append(CleanseComments(
-          self.lines_without_raw_strings[linenum]))
-      elided = self._CollapseStrings(self.lines_without_raw_strings[linenum])
+    for line in self.lines_without_raw_strings:
+      self.lines.append(CleanseComments(line))
+      elided = self._CollapseStrings(line)
       self.elided.append(CleanseComments(elided))
 
   def NumLines(self):
@@ -1970,7 +1939,7 @@ class CleansedLines(object):
     collapsed = ''
     while True:
       # Find the first quote character
-      match = Match(r'^([^\'"]*)([\'"])(.*)$', elided)
+      match = re.match(r'^([^\'"]*)([\'"])(.*)$', elided)
       if not match:
         collapsed += elided
         break
@@ -1995,8 +1964,8 @@ class CleansedLines(object):
         # correctly as long as there are digits on both sides of the
         # separator.  So we are fine as long as we don't see something
         # like "0.'3" (gcc 4.9.0 will not allow this literal).
-        if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
-          match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail)
+        if re.search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
+          match_literal = re.match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail)
           collapsed += head + match_literal.group(1).replace("'", '')
           elided = match_literal.group(2)
         else:
@@ -2025,7 +1994,7 @@ def FindEndOfExpressionInLine(line, startpos, stack):
     On finding an unclosed expression: (-1, None)
     Otherwise: (-1, new stack at end of this line)
   """
-  for i in xrange(startpos, len(line)):
+  for i in range(startpos, len(line)):
     char = line[i]
     if char in '([{':
       # Found start of parenthesized expression, push to expression stack
@@ -2038,7 +2007,7 @@ def FindEndOfExpressionInLine(line, startpos, stack):
           stack.pop()
           if not stack:
             return (-1, None)
-      elif i > 0 and Search(r'\boperator\s*$', line[0:i]):
+      elif i > 0 and re.search(r'\boperator\s*$', line[0:i]):
         # operator<, don't add to stack
         continue
       else:
@@ -2067,7 +2036,7 @@ def FindEndOfExpressionInLine(line, startpos, stack):
 
       # Ignore "->" and operator functions
       if (i > 0 and
-          (line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))):
+          (line[i - 1] == '-' or re.search(r'\boperator\s*$', line[0:i - 1]))):
         continue
 
       # Pop the stack if there is a matching '<'.  Otherwise, ignore
@@ -2114,7 +2083,7 @@ def CloseExpression(clean_lines, linenum, pos):
   """
 
   line = clean_lines.elided[linenum]
-  if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]):
+  if (line[pos] not in '({[<') or re.match(r'<[<=]', line[pos:]):
     return (line, clean_lines.NumLines(), -1)
 
   # Check first line
@@ -2162,8 +2131,8 @@ def FindStartOfExpressionInLine(line, endpos, stack):
       # Ignore it if it's a "->" or ">=" or "operator>"
       if (i > 0 and
           (line[i - 1] == '-' or
-           Match(r'\s>=\s', line[i - 1:]) or
-           Search(r'\boperator\s*$', line[0:i]))):
+           re.match(r'\s>=\s', line[i - 1:]) or
+           re.search(r'\boperator\s*$', line[0:i]))):
         i -= 1
       else:
         stack.append('>')
@@ -2254,7 +2223,7 @@ def CheckForCopyright(filename, lines, error):
 
   # We'll say it should occur by line 10. Don't forget there's a
   # placeholder line at the front.
-  for line in xrange(1, min(len(lines), 11)):
+  for line in range(1, min(len(lines), 11)):
     if re.search(r'Copyright', lines[line], re.I): break
   else:                       # means no copyright line was found
     error(filename, 0, 'legal/copyright', 5,
@@ -2271,7 +2240,7 @@ def GetIndentLevel(line):
   Returns:
     An integer count of leading spaces, possibly zero.
   """
-  indent = Match(r'^( *)\S', line)
+  indent = re.match(r'^( *)\S', line)
   if indent:
     return len(indent.group(1))
   else:
@@ -2326,8 +2295,8 @@ def GetHeaderGuardCPPVariable(filename):
 
   def FixupPathFromRoot():
     if _root_debug:
-      sys.stderr.write("\n_root fixup, _root = '%s', repository name = '%s'\n"
-          % (_root, fileinfo.RepositoryName()))
+      sys.stderr.write(f"\n_root fixup, _root = '{_root}',"
+                       f" repository name = '{fileinfo.RepositoryName()}'\n")
 
     # Process the file path with the --root flag if it was set.
     if not _root:
@@ -2370,7 +2339,7 @@ def GetHeaderGuardCPPVariable(filename):
       return os.path.join(*maybe_path)
 
     if _root_debug:
-      sys.stderr.write("_root ignore, returning %s\n" % (file_path_from_root))
+      sys.stderr.write(f"_root ignore, returning {file_path_from_root}\n")
 
     #   --root=FAKE_DIR is ignored
     return file_path_from_root
@@ -2399,12 +2368,12 @@ def CheckForHeaderGuard(filename, clean_lines, error):
   # and not the general NOLINT or NOLINT(*) syntax.
   raw_lines = clean_lines.lines_without_raw_strings
   for i in raw_lines:
-    if Search(r'//\s*NOLINT\(build/header_guard\)', i):
+    if re.search(r'//\s*NOLINT\(build/header_guard\)', i):
       return
 
   # Allow pragma once instead of header guards
   for i in raw_lines:
-    if Search(r'^\s*#pragma\s+once', i):
+    if re.search(r'^\s*#pragma\s+once', i):
       return
 
   cppvar = GetHeaderGuardCPPVariable(filename)
@@ -2431,8 +2400,7 @@ def CheckForHeaderGuard(filename, clean_lines, error):
 
   if not ifndef or not define or ifndef != define:
     error(filename, 0, 'build/header_guard', 5,
-          'No #ifndef header guard found, suggested CPP variable is: %s' %
-          cppvar)
+          f'No #ifndef header guard found, suggested CPP variable is: {cppvar}')
     return
 
   # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
@@ -2445,41 +2413,41 @@ def CheckForHeaderGuard(filename, clean_lines, error):
     ParseNolintSuppressions(filename, raw_lines[ifndef_linenum], ifndef_linenum,
                             error)
     error(filename, ifndef_linenum, 'build/header_guard', error_level,
-          '#ifndef header guard has wrong style, please use: %s' % cppvar)
+          f'#ifndef header guard has wrong style, please use: {cppvar}')
 
   # Check for "//" comments on endif line.
   ParseNolintSuppressions(filename, raw_lines[endif_linenum], endif_linenum,
                           error)
-  match = Match(r'#endif\s*//\s*' + cppvar + r'(_)?\b', endif)
+  match = re.match(r'#endif\s*//\s*' + cppvar + r'(_)?\b', endif)
   if match:
     if match.group(1) == '_':
       # Issue low severity warning for deprecated double trailing underscore
       error(filename, endif_linenum, 'build/header_guard', 0,
-            '#endif line should be "#endif  // %s"' % cppvar)
+            f'#endif line should be "#endif  // {cppvar}"')
     return
 
   # Didn't find the corresponding "//" comment.  If this file does not
   # contain any "//" comments at all, it could be that the compiler
   # only wants "/**/" comments, look for those instead.
   no_single_line_comments = True
-  for i in xrange(1, len(raw_lines) - 1):
+  for i in range(1, len(raw_lines) - 1):
     line = raw_lines[i]
-    if Match(r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
+    if re.match(r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
       no_single_line_comments = False
       break
 
   if no_single_line_comments:
-    match = Match(r'#endif\s*/\*\s*' + cppvar + r'(_)?\s*\*/', endif)
+    match = re.match(r'#endif\s*/\*\s*' + cppvar + r'(_)?\s*\*/', endif)
     if match:
       if match.group(1) == '_':
         # Low severity warning for double trailing underscore
         error(filename, endif_linenum, 'build/header_guard', 0,
-              '#endif line should be "#endif  /* %s */"' % cppvar)
+              f'#endif line should be "#endif  /* {cppvar} */"')
       return
 
   # Didn't find anything
   error(filename, endif_linenum, 'build/header_guard', 5,
-        '#endif line should be "#endif  // %s"' % cppvar)
+        f'#endif line should be "#endif  // {cppvar}"')
 
 
 def CheckHeaderFileIncluded(filename, include_state, error):
@@ -2487,7 +2455,7 @@ def CheckHeaderFileIncluded(filename, include_state, error):
 
   # Do not check test files
   fileinfo = FileInfo(filename)
-  if Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()):
+  if re.search(_TEST_FILE_SUFFIX, fileinfo.BaseName()):
     return
 
   for ext in GetHeaderExtensions():
@@ -2508,7 +2476,7 @@ def CheckHeaderFileIncluded(filename, include_state, error):
         if not first_include:
           first_include = f[1]
 
-    message = '%s should include its header file %s' % (fileinfo.RepositoryName(), headername)
+    message = f'{fileinfo.RepositoryName()} should include its header file {headername}'
     if include_uses_unix_dir_aliases:
       message += ". Relative paths like . and .. are not allowed."
 
@@ -2533,7 +2501,7 @@ def CheckForBadCharacters(filename, lines, error):
     error: The function to call with any errors found.
   """
   for linenum, line in enumerate(lines):
-    if unicode_escape_decode('\ufffd') in line:
+    if '\ufffd' in line:
       error(filename, linenum, 'readability/utf8', 5,
             'Line contains invalid UTF-8 (or Unicode replacement character).')
     if '\0' in line:
@@ -2645,7 +2613,7 @@ def CheckPosixThreading(filename, clean_lines, linenum, error):
   for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST:
     # Additional pattern matching check to confirm that this is the
     # function we are looking for
-    if Search(pattern, line):
+    if re.search(pattern, line):
       error(filename, linenum, 'runtime/threadsafe_fn', 2,
             'Consider using ' + multithread_safe_func +
             '...) instead of ' + single_thread_func +
@@ -2665,7 +2633,7 @@ def CheckVlogArguments(filename, clean_lines, linenum, error):
     error: The function to call with any errors found.
   """
   line = clean_lines.elided[linenum]
-  if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
+  if re.search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
     error(filename, linenum, 'runtime/vlog', 5,
           'VLOG() should be used with numeric verbosity level.  '
           'Use LOG() if you want symbolic severity levels.')
@@ -2699,17 +2667,17 @@ def CheckInvalidIncrement(filename, clean_lines, linenum, error):
 
 
 def IsMacroDefinition(clean_lines, linenum):
-  if Search(r'^#define', clean_lines[linenum]):
+  if re.search(r'^#define', clean_lines[linenum]):
     return True
 
-  if linenum > 0 and Search(r'\\$', clean_lines[linenum - 1]):
+  if linenum > 0 and re.search(r'\\$', clean_lines[linenum - 1]):
     return True
 
   return False
 
 
 def IsForwardClassDeclaration(clean_lines, linenum):
-  return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
+  return re.match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
 
 
 class _BlockInfo(object):
@@ -2804,15 +2772,15 @@ class _ClassInfo(_BlockInfo):
 
   def CheckBegin(self, filename, clean_lines, linenum, error):
     # Look for a bare ':'
-    if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
+    if re.search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
       self.is_derived = True
 
   def CheckEnd(self, filename, clean_lines, linenum, error):
     # If there is a DISALLOW macro, it should appear near the end of
     # the class.
     seen_last_thing_in_class = False
-    for i in xrange(linenum - 1, self.starting_linenum, -1):
-      match = Search(
+    for i in range(linenum - 1, self.starting_linenum, -1):
+      match = re.search(
           r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' +
           self.name + r'\)',
           clean_lines.elided[i])
@@ -2822,20 +2790,20 @@ class _ClassInfo(_BlockInfo):
                 match.group(1) + ' should be the last thing in the class')
         break
 
-      if not Match(r'^\s*$', clean_lines.elided[i]):
+      if not re.match(r'^\s*$', clean_lines.elided[i]):
         seen_last_thing_in_class = True
 
     # Check that closing brace is aligned with beginning of the class.
     # Only do this if the closing brace is indented by only whitespaces.
     # This means we will not check single-line class definitions.
-    indent = Match(r'^( *)\}', clean_lines.elided[linenum])
+    indent = re.match(r'^( *)\}', clean_lines.elided[linenum])
     if indent and len(indent.group(1)) != self.class_indent:
       if self.is_struct:
         parent = 'struct ' + self.name
       else:
         parent = 'class ' + self.name
       error(filename, linenum, 'whitespace/indent', 3,
-            'Closing brace should be aligned with beginning of %s' % parent)
+            f'Closing brace should be aligned with beginning of {parent}')
 
 
 class _NamespaceInfo(_BlockInfo):
@@ -2862,7 +2830,7 @@ class _NamespaceInfo(_BlockInfo):
     # deciding what these nontrivial things are, so this check is
     # triggered by namespace size only, which works most of the time.
     if (linenum - self.starting_linenum < 10
-        and not Match(r'^\s*};*\s*(//|/\*).*\bnamespace\b', line)):
+        and not re.match(r'^\s*};*\s*(//|/\*).*\bnamespace\b', line)):
       return
 
     # Look for matching comment at end of namespace.
@@ -2879,18 +2847,17 @@ class _NamespaceInfo(_BlockInfo):
     # expected namespace.
     if self.name:
       # Named namespace
-      if not Match((r'^\s*};*\s*(//|/\*).*\bnamespace\s+' +
+      if not re.match((r'^\s*};*\s*(//|/\*).*\bnamespace\s+' +
                     re.escape(self.name) + r'[\*/\.\\\s]*$'),
                    line):
         error(filename, linenum, 'readability/namespace', 5,
-              'Namespace should be terminated with "// namespace %s"' %
-              self.name)
+              f'Namespace should be terminated with "// namespace {self.name}"')
     else:
       # Anonymous namespace
-      if not Match(r'^\s*};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
+      if not re.match(r'^\s*};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
         # If "// namespace anonymous" or "// anonymous namespace (more text)",
         # mention "// anonymous namespace" as an acceptable form
-        if Match(r'^\s*}.*\b(namespace anonymous|anonymous namespace)\b', line):
+        if re.match(r'^\s*}.*\b(namespace anonymous|anonymous namespace)\b', line):
           error(filename, linenum, 'readability/namespace', 5,
                 'Anonymous namespace should be terminated with "// namespace"'
                 ' or "// anonymous namespace"')
@@ -2993,7 +2960,7 @@ class NestingState(object):
     while linenum < clean_lines.NumLines():
       # Find the earliest character that might indicate a template argument
       line = clean_lines.elided[linenum]
-      match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:])
+      match = re.match(r'^[^{};=\[\]\.<>]*(.)', line[pos:])
       if not match:
         linenum += 1
         pos = 0
@@ -3053,11 +3020,11 @@ class NestingState(object):
     Args:
       line: current line to check.
     """
-    if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line):
+    if re.match(r'^\s*#\s*(if|ifdef|ifndef)\b', line):
       # Beginning of #if block, save the nesting stack here.  The saved
       # stack will allow us to restore the parsing state in the #else case.
       self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack)))
-    elif Match(r'^\s*#\s*(else|elif)\b', line):
+    elif re.match(r'^\s*#\s*(else|elif)\b', line):
       # Beginning of #else block
       if self.pp_stack:
         if not self.pp_stack[-1].seen_else:
@@ -3072,7 +3039,7 @@ class NestingState(object):
       else:
         # TODO(unknown): unexpected #else, issue warning?
         pass
-    elif Match(r'^\s*#\s*endif\b', line):
+    elif re.match(r'^\s*#\s*endif\b', line):
       # End of #if or #else blocks.
       if self.pp_stack:
         # If we saw an #else, we will need to restore the nesting
@@ -3144,7 +3111,7 @@ class NestingState(object):
       # declarations even if it weren't followed by a whitespace, this
       # is so that we don't confuse our namespace checker.  The
       # missing spaces will be flagged by CheckSpacing.
-      namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
+      namespace_decl_match = re.match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
       if not namespace_decl_match:
         break
 
@@ -3161,7 +3128,7 @@ class NestingState(object):
     # such as in:
     #   class LOCKABLE API Object {
     #   };
-    class_decl_match = Match(
+    class_decl_match = re.match(
         r'^(\s*(?:template\s*<[\w\s<>,:=]*>\s*)?'
         r'(class|struct)\s+(?:[a-zA-Z0-9_]+\s+)*(\w+(?:::\w+)*))'
         r'(.*)$', line)
@@ -3191,7 +3158,7 @@ class NestingState(object):
     # Update access control if we are inside a class/struct
     if self.stack and isinstance(self.stack[-1], _ClassInfo):
       classinfo = self.stack[-1]
-      access_match = Match(
+      access_match = re.match(
           r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?'
           r':(?:[^:]|$)',
           line)
@@ -3202,7 +3169,7 @@ class NestingState(object):
         # check if the keywords are not preceded by whitespaces.
         indent = access_match.group(1)
         if (len(indent) != classinfo.class_indent + 1 and
-            Match(r'^\s*$', indent)):
+            re.match(r'^\s*$', indent)):
           if classinfo.is_struct:
             parent = 'struct ' + classinfo.name
           else:
@@ -3211,13 +3178,13 @@ class NestingState(object):
           if access_match.group(3):
             slots = access_match.group(3)
           error(filename, linenum, 'whitespace/indent', 3,
-                '%s%s: should be indented +1 space inside %s' % (
-                    access_match.group(2), slots, parent))
+                f'{access_match.group(2)}{slots}:'
+                f' should be indented +1 space inside {parent}')
 
     # Consume braces or semicolons from what's left of the line
     while True:
       # Match first brace, semicolon, or closed parenthesis.
-      matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line)
+      matched = re.match(r'^[^{;)}]*([{;)}])(.*)$', line)
       if not matched:
         break
 
@@ -3228,7 +3195,7 @@ class NestingState(object):
         # stack otherwise.
         if not self.SeenOpenBrace():
           self.stack[-1].seen_open_brace = True
-        elif Match(r'^extern\s*"[^"]*"\s*\{', line):
+        elif re.match(r'^extern\s*"[^"]*"\s*\{', line):
           self.stack.append(_ExternCInfo(linenum))
         else:
           self.stack.append(_BlockInfo(linenum, True))
@@ -3279,12 +3246,10 @@ class NestingState(object):
     for obj in self.stack:
       if isinstance(obj, _ClassInfo):
         error(filename, obj.starting_linenum, 'build/class', 5,
-              'Failed to find complete declaration of class %s' %
-              obj.name)
+              f'Failed to find complete declaration of class {obj.name}')
       elif isinstance(obj, _NamespaceInfo):
         error(filename, obj.starting_linenum, 'build/namespaces', 5,
-              'Failed to find complete declaration of namespace %s' %
-              obj.name)
+              f'Failed to find complete declaration of namespace {obj.name}')
 
 
 def CheckForNonStandardConstructs(filename, clean_lines, linenum,
@@ -3319,25 +3284,25 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
   # Remove comments from the line, but leave in strings for now.
   line = clean_lines.lines[linenum]
 
-  if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
+  if re.search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
     error(filename, linenum, 'runtime/printf_format', 3,
           '%q in format strings is deprecated.  Use %ll instead.')
 
-  if Search(r'printf\s*\(.*".*%\d+\$', line):
+  if re.search(r'printf\s*\(.*".*%\d+\$', line):
     error(filename, linenum, 'runtime/printf_format', 2,
           '%N$ formats are unconventional.  Try rewriting to avoid them.')
 
   # Remove escaped backslashes before looking for undefined escapes.
   line = line.replace('\\\\', '')
 
-  if Search(r'("|\').*\\(%|\[|\(|{)', line):
+  if re.search(r'("|\').*\\(%|\[|\(|{)', line):
     error(filename, linenum, 'build/printf_format', 3,
           '%, [, (, and { are undefined character escapes.  Unescape them.')
 
   # For the rest, work with both comments and strings removed.
   line = clean_lines.elided[linenum]
 
-  if Search(r'\b(const|volatile|void|char|short|int|long'
+  if re.search(r'\b(const|volatile|void|char|short|int|long'
             r'|float|double|signed|unsigned'
             r'|schar|u?int8|u?int16|u?int32|u?int64)'
             r'\s+(register|static|extern|typedef)\b',
@@ -3346,20 +3311,20 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
           'Storage-class specifier (static, extern, typedef, etc) should be '
           'at the beginning of the declaration.')
 
-  if Match(r'\s*#\s*endif\s*[^/\s]+', line):
+  if re.match(r'\s*#\s*endif\s*[^/\s]+', line):
     error(filename, linenum, 'build/endif_comment', 5,
           'Uncommented text after #endif is non-standard.  Use a comment.')
 
-  if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
+  if re.match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
     error(filename, linenum, 'build/forward_decl', 5,
           'Inner-style forward declarations are invalid.  Remove this line.')
 
-  if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
+  if re.search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
             line):
     error(filename, linenum, 'build/deprecated', 3,
           '>? and <? (max and min) operators are non-standard and deprecated.')
 
-  if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
+  if re.search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
     # TODO(unknown): Could it be expanded safely to arbitrary references,
     # without triggering too many false positives? The first
     # attempt triggered 5 warnings for mostly benign code in the regtest, hence
@@ -3384,12 +3349,10 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
 
   # Look for single-argument constructors that aren't marked explicit.
   # Technically a valid construct, but against style.
-  explicit_constructor_match = Match(
+  explicit_constructor_match = re.match(
       r'\s+(?:(?:inline|constexpr)\s+)*(explicit\s+)?'
-      r'(?:(?:inline|constexpr)\s+)*%s\s*'
-      r'\(((?:[^()]|\([^()]*\))*)\)'
-      % re.escape(base_classname),
-      line)
+      rf'(?:(?:inline|constexpr)\s+)*{re.escape(base_classname)}\s*'
+      r'\(((?:[^()]|\([^()]*\))*)\)', line)
 
   if explicit_constructor_match:
     is_marked_explicit = explicit_constructor_match.group(1)
@@ -3428,12 +3391,13 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
                            len(variadic_args) >= 1))
     initializer_list_constructor = bool(
         onearg_constructor and
-        Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
+        re.search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
     copy_constructor = bool(
         onearg_constructor and
-        Match(r'((const\s+(volatile\s+)?)?|(volatile\s+(const\s+)?))?'
-              r'%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&'
-              % re.escape(base_classname), constructor_args[0].strip()))
+        re.match(r'((const\s+(volatile\s+)?)?|(volatile\s+(const\s+)?))?'
+                rf'{re.escape(base_classname)}(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&',
+                constructor_args[0].strip())
+    )
 
     if (not is_marked_explicit and
         onearg_constructor and
@@ -3472,7 +3436,7 @@ def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
                   r'\bfor\s*\((.*)\)\s*{',
                   r'\bwhile\s*\((.*)\)\s*[{;]',
                   r'\bswitch\s*\((.*)\)\s*{'):
-    match = Search(pattern, line)
+    match = re.search(pattern, line)
     if match:
       fncall = match.group(1)    # look inside the parens for function calls
       break
@@ -3491,26 +3455,26 @@ def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
   # Note that we assume the contents of [] to be short enough that
   # they'll never need to wrap.
   if (  # Ignore control structures.
-      not Search(r'\b(if|elif|for|while|switch|return|new|delete|catch|sizeof)\b',
+      not re.search(r'\b(if|elif|for|while|switch|return|new|delete|catch|sizeof)\b',
                  fncall) and
       # Ignore pointers/references to functions.
-      not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
+      not re.search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
       # Ignore pointers/references to arrays.
-      not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
-    if Search(r'\w\s*\(\s(?!\s*\\$)', fncall):      # a ( used for a fn call
+      not re.search(r' \([^)]+\)\[[^\]]+\]', fncall)):
+    if re.search(r'\w\s*\(\s(?!\s*\\$)', fncall):      # a ( used for a fn call
       error(filename, linenum, 'whitespace/parens', 4,
             'Extra space after ( in function call')
-    elif Search(r'\(\s+(?!(\s*\\)|\()', fncall):
+    elif re.search(r'\(\s+(?!(\s*\\)|\()', fncall):
       error(filename, linenum, 'whitespace/parens', 2,
             'Extra space after (')
-    if (Search(r'\w\s+\(', fncall) and
-        not Search(r'_{0,2}asm_{0,2}\s+_{0,2}volatile_{0,2}\s+\(', fncall) and
-        not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and
-        not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and
-        not Search(r'\bcase\s+\(', fncall)):
+    if (re.search(r'\w\s+\(', fncall) and
+        not re.search(r'_{0,2}asm_{0,2}\s+_{0,2}volatile_{0,2}\s+\(', fncall) and
+        not re.search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and
+        not re.search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and
+        not re.search(r'\bcase\s+\(', fncall)):
       # TODO(unknown): Space after an operator function seem to be a common
       # error, silence those for now by restricting them to highest verbosity.
-      if Search(r'\boperator_*\b', line):
+      if re.search(r'\boperator_*\b', line):
         error(filename, linenum, 'whitespace/parens', 0,
               'Extra space before ( in function call')
       else:
@@ -3518,10 +3482,10 @@ def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
               'Extra space before ( in function call')
     # If the ) is followed only by a newline or a { + newline, assume it's
     # part of a control statement (if/while/etc), and don't complain
-    if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
+    if re.search(r'[^)]\s+\)\s*[^{\s]', fncall):
       # If the closing parenthesis is preceded by only whitespaces,
       # try to give a more descriptive error message.
-      if Search(r'^\s+\)', fncall):
+      if re.search(r'^\s+\)', fncall):
         error(filename, linenum, 'whitespace/parens', 2,
               'Closing ) should be moved to the previous line')
       else:
@@ -3587,28 +3551,28 @@ def CheckForFunctionLengths(filename, clean_lines, linenum,
 
   starting_func = False
   regexp = r'(\w(\w|::|\*|\&|\s)*)\('  # decls * & space::name( ...
-  match_result = Match(regexp, line)
+  match_result = re.match(regexp, line)
   if match_result:
     # If the name is all caps and underscores, figure it's a macro and
     # ignore it, unless it's TEST or TEST_F.
     function_name = match_result.group(1).split()[-1]
     if function_name == 'TEST' or function_name == 'TEST_F' or (
-        not Match(r'[A-Z_]+$', function_name)):
+        not re.match(r'[A-Z_]+$', function_name)):
       starting_func = True
 
   if starting_func:
     body_found = False
-    for start_linenum in xrange(linenum, clean_lines.NumLines()):
+    for start_linenum in range(linenum, clean_lines.NumLines()):
       start_line = lines[start_linenum]
       joined_line += ' ' + start_line.lstrip()
-      if Search(r'(;|})', start_line):  # Declarations and trivial functions
+      if re.search(r'(;|})', start_line):  # Declarations and trivial functions
         body_found = True
         break                              # ... ignore
-      if Search(r'{', start_line):
+      if re.search(r'{', start_line):
         body_found = True
-        function = Search(r'((\w|:)*)\(', line).group(1)
-        if Match(r'TEST', function):    # Handle TEST... macros
-          parameter_regexp = Search(r'(\(.*\))', joined_line)
+        function = re.search(r'((\w|:)*)\(', line).group(1)
+        if re.match(r'TEST', function):    # Handle TEST... macros
+          parameter_regexp = re.search(r'(\(.*\))', joined_line)
           if parameter_regexp:             # Ignore bad syntax
             function += parameter_regexp.group(1)
         else:
@@ -3619,10 +3583,10 @@ def CheckForFunctionLengths(filename, clean_lines, linenum,
       # No body for the function (or evidence of a non-function) was found.
       error(filename, linenum, 'readability/fn_size', 5,
             'Lint failed to find start of function body.')
-  elif Match(r'^\}\s*$', line):  # function end
+  elif re.match(r'^\}\s*$', line):  # function end
     function_state.Check(error, filename, linenum)
     function_state.End()
-  elif not Match(r'^\s*$', line):
+  elif not re.match(r'^\s*$', line):
     function_state.Count()  # Count non-blank/non-comment lines.
 
 
@@ -3644,7 +3608,7 @@ def CheckComment(line, filename, linenum, next_line_start, error):
     # Check if the // may be in quotes.  If so, ignore it
     if re.sub(r'\\.', '', line[0:commentpos]).count('"') % 2 == 0:
       # Allow one space for new scopes, two spaces otherwise:
-      if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and
+      if (not (re.match(r'^.*{ *//', line) and next_line_start == commentpos) and
           ((commentpos >= 1 and
             line[commentpos-1] not in string.whitespace) or
            (commentpos >= 2 and
@@ -3669,7 +3633,8 @@ def CheckComment(line, filename, linenum, next_line_start, error):
                 '"// TODO(my_username): Stuff."')
 
         middle_whitespace = match.group(3)
-        # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison
+        # Comparisons made explicit for correctness
+        #  -- pylint: disable=g-explicit-bool-comparison
         if middle_whitespace != ' ' and middle_whitespace != '':
           error(filename, linenum, 'whitespace/todo', 2,
                 'TODO(my_username) should be followed by a space')
@@ -3677,8 +3642,8 @@ def CheckComment(line, filename, linenum, next_line_start, error):
       # If the comment contains an alphanumeric character, there
       # should be a space somewhere between it and the // unless
       # it's a /// or //! Doxygen comment.
-      if (Match(r'//[^ ]*\w', comment) and
-          not Match(r'(///|//\!)(\s+|$)', comment)):
+      if (re.match(r'//[^ ]*\w', comment) and
+          not re.match(r'(///|//\!)(\s+|$)', comment)):
         error(filename, linenum, 'whitespace/comments', 4,
               'Should have a space between // and comment')
 
@@ -3741,12 +3706,12 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
       # the previous line is indented 6 spaces, which may happen when the
       # initializers of a constructor do not fit into a 80 column line.
       exception = False
-      if Match(r' {6}\w', prev_line):  # Initializer list?
+      if re.match(r' {6}\w', prev_line):  # Initializer list?
         # We are looking for the opening column of initializer list, which
         # should be indented 4 spaces to cause 6 space indentation afterwards.
         search_position = linenum-2
         while (search_position >= 0
-               and Match(r' {6}\w', elided[search_position])):
+               and re.match(r' {6}\w', elided[search_position])):
           search_position -= 1
         exception = (search_position >= 0
                      and elided[search_position][:5] == '    :')
@@ -3757,9 +3722,9 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
         # or colon (for initializer lists) we assume that it is the last line of
         # a function header.  If we have a colon indented 4 spaces, it is an
         # initializer list.
-        exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
+        exception = (re.match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
                            prev_line)
-                     or Match(r' {4}:', prev_line))
+                     or re.match(r' {4}:', prev_line))
 
       if not exception:
         error(filename, linenum, 'whitespace/blank_line', 2,
@@ -3776,16 +3741,16 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
     if linenum + 1 < clean_lines.NumLines():
       next_line = raw[linenum + 1]
       if (next_line
-          and Match(r'\s*}', next_line)
+          and re.match(r'\s*}', next_line)
           and next_line.find('} else ') == -1):
         error(filename, linenum, 'whitespace/blank_line', 3,
               'Redundant blank line at the end of a code block '
               'should be deleted.')
 
-    matched = Match(r'\s*(public|protected|private):', prev_line)
+    matched = re.match(r'\s*(public|protected|private):', prev_line)
     if matched:
       error(filename, linenum, 'whitespace/blank_line', 3,
-            'Do not leave a blank line after "%s:"' % matched.group(1))
+            f'Do not leave a blank line after "{matched.group(1)}:"')
 
   # Next, check comments
   next_line_start = 0
@@ -3799,15 +3764,15 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
 
   # You shouldn't have spaces before your brackets, except for C++11 attributes
   # or maybe after 'delete []', 'return []() {};', or 'auto [abc, ...] = ...;'.
-  if (Search(r'\w\s+\[(?!\[)', line) and
-      not Search(r'(?:auto&?|delete|return)\s+\[', line)):
+  if (re.search(r'\w\s+\[(?!\[)', line) and
+      not re.search(r'(?:auto&?|delete|return)\s+\[', line)):
     error(filename, linenum, 'whitespace/braces', 5,
           'Extra space before [')
 
   # In range-based for, we wanted spaces before and after the colon, but
   # not around "::" tokens that might appear.
-  if (Search(r'for *\(.*[^:]:[^: ]', line) or
-      Search(r'for *\(.*[^: ]:[^:]', line)):
+  if (re.search(r'for *\(.*[^:]:[^: ]', line) or
+      re.search(r'for *\(.*[^: ]:[^:]', line)):
     error(filename, linenum, 'whitespace/forcolon', 2,
           'Missing space around colon in range-based for loop')
 
@@ -3830,7 +3795,7 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
   # The replacement is done repeatedly to avoid false positives from
   # operators that call operators.
   while True:
-    match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
+    match = re.match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
     if match:
       line = match.group(1) + ('_' * len(match.group(2))) + match.group(3)
     else:
@@ -3840,12 +3805,12 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
   # Otherwise not.  Note we only check for non-spaces on *both* sides;
   # sometimes people put non-spaces on one side when aligning ='s among
   # many lines (not that this is behavior that I approve of...)
-  if ((Search(r'[\w.]=', line) or
-       Search(r'=[\w.]', line))
-      and not Search(r'\b(if|while|for) ', line)
+  if ((re.search(r'[\w.]=', line) or
+       re.search(r'=[\w.]', line))
+      and not re.search(r'\b(if|while|for) ', line)
       # Operators taken from [lex.operators] in C++11 standard.
-      and not Search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
-      and not Search(r'operator=', line)):
+      and not re.search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
+      and not re.search(r'operator=', line)):
     error(filename, linenum, 'whitespace/operators', 4,
           'Missing spaces around =')
 
@@ -3864,16 +3829,17 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
   #
   # Note that && is not included here.  This is because there are too
   # many false positives due to RValue references.
-  match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
+  match = re.search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
   if match:
+    # TODO: support alternate operators
     error(filename, linenum, 'whitespace/operators', 3,
-          'Missing spaces around %s' % match.group(1))
-  elif not Match(r'#.*include', line):
+          f'Missing spaces around {match.group(1)}')
+  elif not re.match(r'#.*include', line):
     # Look for < that is not surrounded by spaces.  This is only
     # triggered if both sides are missing spaces, even though
     # technically should should flag if at least one side is missing a
     # space.  This is done to avoid some false positives with shifts.
-    match = Match(r'^(.*[^\s<])<[^\s=<,]', line)
+    match = re.match(r'^(.*[^\s<])<[^\s=<,]', line)
     if match:
       (_, _, end_pos) = CloseExpression(
           clean_lines, linenum, len(match.group(1)))
@@ -3884,7 +3850,7 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
     # Look for > that is not surrounded by spaces.  Similar to the
     # above, we only trigger if both sides are missing spaces to avoid
     # false positives with shifts.
-    match = Match(r'^(.*[^-\s>])>[^\s=>,]', line)
+    match = re.match(r'^(.*[^-\s>])>[^\s=>,]', line)
     if match:
       (_, _, start_pos) = ReverseCloseExpression(
           clean_lines, linenum, len(match.group(1)))
@@ -3897,7 +3863,7 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
   #
   # We also allow operators following an opening parenthesis, since
   # those tend to be macros that deal with operators.
-  match = Search(r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line)
+  match = re.search(r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line)
   if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and
       not (match.group(1) == 'operator' and match.group(2) == ';')):
     error(filename, linenum, 'whitespace/operators', 3,
@@ -3915,16 +3881,16 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
   # follows would be part of an identifier, and there should still be
   # a space separating the template type and the identifier.
   #   type<type<type>> alpha
-  match = Search(r'>>[a-zA-Z_]', line)
+  match = re.search(r'>>[a-zA-Z_]', line)
   if match:
     error(filename, linenum, 'whitespace/operators', 3,
           'Missing spaces around >>')
 
   # There shouldn't be space around unary operators
-  match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
+  match = re.search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
   if match:
     error(filename, linenum, 'whitespace/operators', 4,
-          'Extra space for operator %s' % match.group(1))
+          f'Extra space for operator {match.group(1)}')
 
 
 def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
@@ -3939,30 +3905,29 @@ def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
   line = clean_lines.elided[linenum]
 
   # No spaces after an if, while, switch, or for
-  match = Search(r' (if\(|for\(|while\(|switch\()', line)
+  match = re.search(r' (if\(|for\(|while\(|switch\()', line)
   if match:
     error(filename, linenum, 'whitespace/parens', 5,
-          'Missing space before ( in %s' % match.group(1))
+          f'Missing space before ( in {match.group(1)}')
 
   # For if/for/while/switch, the left and right parens should be
   # consistent about how many spaces are inside the parens, and
   # there should either be zero or one spaces inside the parens.
   # We don't want: "if ( foo)" or "if ( foo   )".
   # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
-  match = Search(r'\b(if|for|while|switch)\s*'
+  match = re.search(r'\b(if|for|while|switch)\s*'
                  r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
                  line)
   if match:
     if len(match.group(2)) != len(match.group(4)):
       if not (match.group(3) == ';' and
               len(match.group(2)) == 1 + len(match.group(4)) or
-              not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)):
+              not match.group(2) and re.search(r'\bfor\s*\(.*; \)', line)):
         error(filename, linenum, 'whitespace/parens', 5,
-              'Mismatching spaces inside () in %s' % match.group(1))
+              f'Mismatching spaces inside () in {match.group(1)}')
     if len(match.group(2)) not in [0, 1]:
       error(filename, linenum, 'whitespace/parens', 5,
-            'Should have zero or one spaces inside ( and ) in %s' %
-            match.group(1))
+            f'Should have zero or one spaces inside ( and ) in {match.group(1)}')
 
 
 def CheckCommaSpacing(filename, clean_lines, linenum, error):
@@ -3987,8 +3952,8 @@ def CheckCommaSpacing(filename, clean_lines, linenum, error):
   # verify that lines contain missing whitespaces, second pass on raw
   # lines to confirm that those missing whitespaces are not due to
   # elided comments.
-  if (Search(r',[^,\s]', ReplaceAll(r'\boperator\s*,\s*\(', 'F(', line)) and
-      Search(r',[^,\s]', raw[linenum])):
+  if (re.search(r',[^,\s]', re.sub(r'\boperator\s*,\s*\(', 'F(', line)) and
+      re.search(r',[^,\s]', raw[linenum])):
     error(filename, linenum, 'whitespace/comma', 3,
           'Missing space after ,')
 
@@ -3996,7 +3961,7 @@ def CheckCommaSpacing(filename, clean_lines, linenum, error):
   # except for few corner cases
   # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more
   # space after ;
-  if Search(r';[^\s};\\)/]', line):
+  if re.search(r';[^\s};\\)/]', line):
     error(filename, linenum, 'whitespace/semicolon', 3,
           'Missing space after ;')
 
@@ -4013,7 +3978,7 @@ def _IsType(clean_lines, nesting_state, expr):
     True, if token looks like a type.
   """
   # Keep only the last token in the expression
-  last_word = Match(r'^.*(\b\S+)$', expr)
+  last_word = re.match(r'^.*(\b\S+)$', expr)
   if last_word:
     token = last_word.group(1)
   else:
@@ -4056,8 +4021,8 @@ def _IsType(clean_lines, nesting_state, expr):
       continue
 
     # Look for typename in the specified range
-    for i in xrange(first_line, last_line + 1, 1):
-      if Search(typename_pattern, clean_lines.elided[i]):
+    for i in range(first_line, last_line + 1, 1):
+      if re.search(typename_pattern, clean_lines.elided[i]):
         return True
     block_index -= 1
 
@@ -4083,7 +4048,7 @@ def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error):
   # And since you should never have braces at the beginning of a line,
   # this is an easy test.  Except that braces used for initialization don't
   # follow the same rule; we often don't want spaces before those.
-  match = Match(r'^(.*[^ ({>]){', line)
+  match = re.match(r'^(.*[^ ({>]){', line)
 
   if match:
     # Try a bit harder to check for brace initialization.  This
@@ -4120,34 +4085,34 @@ def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error):
     trailing_text = ''
     if endpos > -1:
       trailing_text = endline[endpos:]
-    for offset in xrange(endlinenum + 1,
+    for offset in range(endlinenum + 1,
                          min(endlinenum + 3, clean_lines.NumLines() - 1)):
       trailing_text += clean_lines.elided[offset]
     # We also suppress warnings for `uint64_t{expression}` etc., as the style
     # guide recommends brace initialization for integral types to avoid
     # overflow/truncation.
-    if (not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text)
+    if (not re.match(r'^[\s}]*[{.;,)<>\]:]', trailing_text)
         and not _IsType(clean_lines, nesting_state, leading_text)):
       error(filename, linenum, 'whitespace/braces', 5,
             'Missing space before {')
 
   # Make sure '} else {' has spaces.
-  if Search(r'}else', line):
+  if re.search(r'}else', line):
     error(filename, linenum, 'whitespace/braces', 5,
           'Missing space before else')
 
   # You shouldn't have a space before a semicolon at the end of the line.
   # There's a special case for "for" since the style guide allows space before
   # the semicolon there.
-  if Search(r':\s*;\s*$', line):
+  if re.search(r':\s*;\s*$', line):
     error(filename, linenum, 'whitespace/semicolon', 5,
           'Semicolon defining empty statement. Use {} instead.')
-  elif Search(r'^\s*;\s*$', line):
+  elif re.search(r'^\s*;\s*$', line):
     error(filename, linenum, 'whitespace/semicolon', 5,
           'Line contains only semicolon. If this should be an empty statement, '
           'use {} instead.')
-  elif (Search(r'\s+;\s*$', line) and
-        not Search(r'\bfor\b', line)):
+  elif (re.search(r'\s+;\s*$', line) and
+        not re.search(r'\bfor\b', line)):
     error(filename, linenum, 'whitespace/semicolon', 5,
           'Extra space before last semicolon. If this should be an empty '
           'statement, use {} instead.')
@@ -4166,7 +4131,7 @@ def IsDecltype(clean_lines, linenum, column):
   (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column)
   if start_col < 0:
     return False
-  if Search(r'\bdecltype\s*$', text[0:start_col]):
+  if re.search(r'\bdecltype\s*$', text[0:start_col]):
     return True
   return False
 
@@ -4197,7 +4162,7 @@ def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
       linenum <= class_info.starting_linenum):
     return
 
-  matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum])
+  matched = re.match(r'\s*(public|protected|private):', clean_lines.lines[linenum])
   if matched:
     # Issue warning if the line before public/protected/private was
     # not a blank line, but don't do this if the previous line contains
@@ -4209,20 +4174,20 @@ def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
     # common when defining classes in C macros.
     prev_line = clean_lines.lines[linenum - 1]
     if (not IsBlankLine(prev_line) and
-        not Search(r'\b(class|struct)\b', prev_line) and
-        not Search(r'\\$', prev_line)):
+        not re.search(r'\b(class|struct)\b', prev_line) and
+        not re.search(r'\\$', prev_line)):
       # Try a bit harder to find the beginning of the class.  This is to
       # account for multi-line base-specifier lists, e.g.:
       #   class Derived
       #       : public Base {
       end_class_head = class_info.starting_linenum
       for i in range(class_info.starting_linenum, linenum):
-        if Search(r'\{\s*$', clean_lines.lines[i]):
+        if re.search(r'\{\s*$', clean_lines.lines[i]):
           end_class_head = i
           break
       if end_class_head < linenum - 1:
         error(filename, linenum, 'whitespace/blank_line', 3,
-              '"%s:" should be preceded by a blank line' % matched.group(1))
+              f'"{matched.group(1)}:" should be preceded by a blank line')
 
 
 def GetPreviousNonBlankLine(clean_lines, linenum):
@@ -4260,7 +4225,7 @@ def CheckBraces(filename, clean_lines, linenum, error):
 
   line = clean_lines.elided[linenum]        # get rid of comments and strings
 
-  if Match(r'\s*{\s*$', line):
+  if re.match(r'\s*{\s*$', line):
     # We allow an open brace to start a line in the case where someone is using
     # braces in a block to explicitly create a new scope, which is commonly used
     # to control the lifetime of stack-allocated variables.  Braces are also
@@ -4271,23 +4236,23 @@ def CheckBraces(filename, clean_lines, linenum, error):
     # following line if it is part of an array initialization and would not fit
     # within the 80 character limit of the preceding line.
     prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
-    if (not Search(r'[,;:}{(]\s*$', prevline) and
-        not Match(r'\s*#', prevline) and
+    if (not re.search(r'[,;:}{(]\s*$', prevline) and
+        not re.match(r'\s*#', prevline) and
         not (GetLineWidth(prevline) > _line_length - 2 and '[]' in prevline)):
       error(filename, linenum, 'whitespace/braces', 4,
             '{ should almost always be at the end of the previous line')
 
   # An else clause should be on the same line as the preceding closing brace.
-  if Match(r'\s*else\b\s*(?:if\b|\{|$)', line):
+  if re.match(r'\s*else\b\s*(?:if\b|\{|$)', line):
     prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
-    if Match(r'\s*}\s*$', prevline):
+    if re.match(r'\s*}\s*$', prevline):
       error(filename, linenum, 'whitespace/newline', 4,
             'An else should appear on the same line as the preceding }')
 
   # If braces come on one side of an else, they should be on both.
   # However, we have to worry about "else if" that spans multiple lines!
-  if Search(r'else if\s*\(', line):       # could be multi-line if
-    brace_on_left = bool(Search(r'}\s*else if\s*\(', line))
+  if re.search(r'else if\s*\(', line):       # could be multi-line if
+    brace_on_left = bool(re.search(r'}\s*else if\s*\(', line))
     # find the ( after the if
     pos = line.find('else if')
     pos = line.find('(', pos)
@@ -4297,17 +4262,17 @@ def CheckBraces(filename, clean_lines, linenum, error):
       if brace_on_left != brace_on_right:    # must be brace after if
         error(filename, linenum, 'readability/braces', 5,
               'If an else has a brace on one side, it should have it on both')
-  elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
+  elif re.search(r'}\s*else[^{]*$', line) or re.match(r'[^}]*else\s*{', line):
     error(filename, linenum, 'readability/braces', 5,
           'If an else has a brace on one side, it should have it on both')
 
   # Likewise, an else should never have the else clause on the same line
-  if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
+  if re.search(r'\belse [^\s{]', line) and not re.search(r'\belse if\b', line):
     error(filename, linenum, 'whitespace/newline', 4,
           'Else clause should never be on same line as else (use 2 lines)')
 
   # In the same way, a do/while should never be on one line
-  if Match(r'\s*do [^\s{]', line):
+  if re.match(r'\s*do [^\s{]', line):
     error(filename, linenum, 'whitespace/newline', 4,
           'do/while clauses should not be on a single line')
 
@@ -4318,21 +4283,21 @@ def CheckBraces(filename, clean_lines, linenum, error):
   # its line, and the line after that should have an indent level equal to or
   # lower than the if. We also check for ambiguous if/else nesting without
   # braces.
-  if_else_match = Search(r'\b(if\s*(|constexpr)\s*\(|else\b)', line)
-  if if_else_match and not Match(r'\s*#', line):
+  if_else_match = re.search(r'\b(if\s*(|constexpr)\s*\(|else\b)', line)
+  if if_else_match and not re.match(r'\s*#', line):
     if_indent = GetIndentLevel(line)
     endline, endlinenum, endpos = line, linenum, if_else_match.end()
-    if_match = Search(r'\bif\s*(|constexpr)\s*\(', line)
+    if_match = re.search(r'\bif\s*(|constexpr)\s*\(', line)
     if if_match:
       # This could be a multiline if condition, so find the end first.
       pos = if_match.end() - 1
       (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos)
     # Check for an opening brace, either directly after the if or on the next
     # line. If found, this isn't a single-statement conditional.
-    if (not Match(r'\s*{', endline[endpos:])
-        and not (Match(r'\s*$', endline[endpos:])
+    if (not re.match(r'\s*{', endline[endpos:])
+        and not (re.match(r'\s*$', endline[endpos:])
                  and endlinenum < (len(clean_lines.elided) - 1)
-                 and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))):
+                 and re.match(r'\s*{', clean_lines.elided[endlinenum + 1]))):
       while (endlinenum < len(clean_lines.elided)
              and ';' not in clean_lines.elided[endlinenum][endpos:]):
         endlinenum += 1
@@ -4342,11 +4307,11 @@ def CheckBraces(filename, clean_lines, linenum, error):
         # We allow a mix of whitespace and closing braces (e.g. for one-liner
         # methods) and a single \ after the semicolon (for macros)
         endpos = endline.find(';')
-        if not Match(r';[\s}]*(\\?)$', endline[endpos:]):
+        if not re.match(r';[\s}]*(\\?)$', endline[endpos:]):
           # Semicolon isn't the last character, there's something trailing.
           # Output a warning if the semicolon is not contained inside
           # a lambda expression.
-          if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
+          if not re.match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
                        endline):
             error(filename, linenum, 'readability/braces', 4,
                   'If/else bodies with multiple statements require braces')
@@ -4357,7 +4322,7 @@ def CheckBraces(filename, clean_lines, linenum, error):
           # With ambiguous nested if statements, this will error out on the
           # if that *doesn't* match the else, regardless of whether it's the
           # inner one or outer one.
-          if (if_match and Match(r'\s*else\b', next_line)
+          if (if_match and re.match(r'\s*else\b', next_line)
               and next_indent != if_indent):
             error(filename, linenum, 'readability/braces', 4,
                   'Else clause should be indented at the same level as if. '
@@ -4423,7 +4388,7 @@ def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
   #    to namespaces.  For now we do not warn for this case.
   #
   # Try matching case 1 first.
-  match = Match(r'^(.*\)\s*)\{', line)
+  match = re.match(r'^(.*\)\s*)\{', line)
   if match:
     # Matched closing parenthesis (case 1).  Check the token before the
     # matching opening parenthesis, and don't warn if it looks like a
@@ -4456,27 +4421,27 @@ def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
         clean_lines, linenum, closing_brace_pos)
     if opening_parenthesis[2] > -1:
       line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
-      macro = Search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix)
-      func = Match(r'^(.*\])\s*$', line_prefix)
+      macro = re.search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix)
+      func = re.match(r'^(.*\])\s*$', line_prefix)
       if ((macro and
            macro.group(1) not in (
                'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
                'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
                'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
-          (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or
-          Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or
-          Search(r'\bdecltype$', line_prefix) or
-          Search(r'\s+=\s*$', line_prefix)):
+          (func and not re.search(r'\boperator\s*\[\s*\]', func.group(1))) or
+          re.search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or
+          re.search(r'\bdecltype$', line_prefix) or
+          re.search(r'\s+=\s*$', line_prefix)):
         match = None
     if (match and
         opening_parenthesis[1] > 1 and
-        Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
+        re.search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
       # Multi-line lambda-expression
       match = None
 
   else:
     # Try matching cases 2-3.
-    match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line)
+    match = re.match(r'^(.*(?:else|\)\s*const)\s*)\{', line)
     if not match:
       # Try matching cases 4-6.  These are always matched on separate lines.
       #
@@ -4487,14 +4452,14 @@ def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
       #     // blank line
       #   }
       prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
-      if prevline and Search(r'[;{}]\s*$', prevline):
-        match = Match(r'^(\s*)\{', line)
+      if prevline and re.search(r'[;{}]\s*$', prevline):
+        match = re.match(r'^(\s*)\{', line)
 
   # Check matching closing brace
   if match:
     (endline, endlinenum, endpos) = CloseExpression(
         clean_lines, linenum, len(match.group(1)))
-    if endpos > -1 and Match(r'^\s*;', endline[endpos:]):
+    if endpos > -1 and re.match(r'^\s*;', endline[endpos:]):
       # Current {} pair is eligible for semicolon check, and we have found
       # the redundant semicolon, output warning here.
       #
@@ -4531,7 +4496,7 @@ def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
   # We also check "if" blocks here, since an empty conditional block
   # is likely an error.
   line = clean_lines.elided[linenum]
-  matched = Match(r'\s*(for|while|if)\s*\(', line)
+  matched = re.match(r'\s*(for|while|if)\s*\(', line)
   if matched:
     # Find the end of the conditional expression.
     (end_line, end_linenum, end_pos) = CloseExpression(
@@ -4540,7 +4505,7 @@ def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
     # Output warning if what follows the condition expression is a semicolon.
     # No warning for all other cases, including whitespace or newline, since we
     # have a separate check for semicolons preceded by whitespace.
-    if end_pos >= 0 and Match(r';', end_line[end_pos:]):
+    if end_pos >= 0 and re.match(r';', end_line[end_pos:]):
       if matched.group(1) == 'if':
         error(filename, end_linenum, 'whitespace/empty_conditional_body', 5,
               'Empty conditional bodies should use {}')
@@ -4556,8 +4521,8 @@ def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
       opening_linenum = end_linenum
       opening_line_fragment = end_line[end_pos:]
       # Loop until EOF or find anything that's not whitespace or opening {.
-      while not Search(r'^\s*\{', opening_line_fragment):
-        if Search(r'^(?!\s*$)', opening_line_fragment):
+      while not re.search(r'^\s*\{', opening_line_fragment):
+        if re.search(r'^(?!\s*$)', opening_line_fragment):
           # Conditional has no brackets.
           return
         opening_linenum += 1
@@ -4604,8 +4569,8 @@ def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
       current_linenum = closing_linenum
       current_line_fragment = closing_line[closing_pos:]
       # Loop until EOF or find anything that's not whitespace or else clause.
-      while Search(r'^\s*$|^(?=\s*else)', current_line_fragment):
-        if Search(r'^(?=\s*else)', current_line_fragment):
+      while re.search(r'^\s*$|^(?=\s*else)', current_line_fragment):
+        if re.search(r'^(?=\s*else)', current_line_fragment):
           # Found an else clause, so don't log an error.
           return
         current_linenum += 1
@@ -4634,7 +4599,7 @@ def FindCheckMacro(line):
       # to make sure that we are matching the expected CHECK macro, as
       # opposed to some other macro that happens to contain the CHECK
       # substring.
-      matched = Match(r'^(.*\b' + macro + r'\s*)\(', line)
+      matched = re.match(r'^(.*\b' + macro + r'\s*)\(', line)
       if not matched:
         continue
       return (macro, len(matched.group(1)))
@@ -4666,14 +4631,14 @@ def CheckCheck(filename, clean_lines, linenum, error):
   # If the check macro is followed by something other than a
   # semicolon, assume users will log their own custom error messages
   # and don't suggest any replacements.
-  if not Match(r'\s*;', last_line[end_pos:]):
+  if not re.match(r'\s*;', last_line[end_pos:]):
     return
 
   if linenum == end_line:
     expression = lines[linenum][start_pos + 1:end_pos - 1]
   else:
     expression = lines[linenum][start_pos + 1:]
-    for i in xrange(linenum + 1, end_line):
+    for i in range(linenum + 1, end_line):
       expression += lines[i]
     expression += last_line[0:end_pos - 1]
 
@@ -4684,7 +4649,7 @@ def CheckCheck(filename, clean_lines, linenum, error):
   rhs = ''
   operator = None
   while expression:
-    matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||'
+    matched = re.match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||'
                     r'==|!=|>=|>|<=|<|\()(.*)$', expression)
     if matched:
       token = matched.group(1)
@@ -4718,9 +4683,9 @@ def CheckCheck(filename, clean_lines, linenum, error):
       # characters at once if possible.  Trivial benchmark shows that this
       # is more efficient when the operands are longer than a single
       # character, which is generally the case.
-      matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression)
+      matched = re.match(r'^([^-=!<>()&|]+)(.*)$', expression)
       if not matched:
-        matched = Match(r'^(\s*\S)(.*)$', expression)
+        matched = re.match(r'^(\s*\S)(.*)$', expression)
         if not matched:
           break
       lhs += matched.group(1)
@@ -4744,7 +4709,7 @@ def CheckCheck(filename, clean_lines, linenum, error):
   lhs = lhs.strip()
   rhs = rhs.strip()
   match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$'
-  if Match(match_constant, lhs) or Match(match_constant, rhs):
+  if re.match(match_constant, lhs) or re.match(match_constant, rhs):
     # Note: since we know both lhs and rhs, we can provide a more
     # descriptive error message like:
     #   Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42)
@@ -4754,9 +4719,8 @@ def CheckCheck(filename, clean_lines, linenum, error):
     # We are still keeping the less descriptive message because if lhs
     # or rhs gets long, the error message might become unreadable.
     error(filename, linenum, 'readability/check', 2,
-          'Consider using %s instead of %s(a %s b)' % (
-              _CHECK_REPLACEMENT[check_macro][operator],
-              check_macro, operator))
+          f'Consider using {_CHECK_REPLACEMENT[check_macro][operator]}'
+          f' instead of {check_macro}(a {operator} b)')
 
 
 def CheckAltTokens(filename, clean_lines, linenum, error):
@@ -4771,7 +4735,7 @@ def CheckAltTokens(filename, clean_lines, linenum, error):
   line = clean_lines.elided[linenum]
 
   # Avoid preprocessor lines
-  if Match(r'^\s*#', line):
+  if re.match(r'^\s*#', line):
     return
 
   # Last ditch effort to avoid multi-line comments.  This will not help
@@ -4787,8 +4751,8 @@ def CheckAltTokens(filename, clean_lines, linenum, error):
 
   for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
     error(filename, linenum, 'readability/alt_tokens', 2,
-          'Use operator %s instead of %s' % (
-              _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
+          f'Use operator {_ALT_TOKEN_REPLACEMENT[match.group(2)]}'
+          f' instead of {match.group(2)}')
 
 
 def GetLineWidth(line):
@@ -4801,7 +4765,7 @@ def GetLineWidth(line):
     The width of the line in column positions, accounting for Unicode
     combining characters and wide characters.
   """
-  if isinstance(line, unicode):
+  if isinstance(line, str):
     width = 0
     for uc in unicodedata.normalize('NFC', line):
       if unicodedata.east_asian_width(uc) in ('W', 'F'):
@@ -4875,11 +4839,11 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
   # We also don't check for lines that look like continuation lines
   # (of lines ending in double quotes, commas, equals, or angle brackets)
   # because the rules for how to indent those are non-trivial.
-  if (not Search(r'[",=><] *$', prev) and
+  if (not re.search(r'[",=><] *$', prev) and
       (initial_spaces == 1 or initial_spaces == 3) and
-      not Match(scope_or_label_pattern, cleansed_line) and
+      not re.match(scope_or_label_pattern, cleansed_line) and
       not (clean_lines.raw_lines[linenum] != line and
-           Match(r'^\s*""', line))):
+           re.match(r'^\s*""', line))):
     error(filename, linenum, 'whitespace/indent', 3,
           'Weird number of spaces at line-start.  '
           'Are you using a 2-space indent?')
@@ -4892,9 +4856,9 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
   is_header_guard = False
   if IsHeaderExtension(file_extension):
     cppvar = GetHeaderGuardCPPVariable(filename)
-    if (line.startswith('#ifndef %s' % cppvar) or
-        line.startswith('#define %s' % cppvar) or
-        line.startswith('#endif  // %s' % cppvar)):
+    if (line.startswith(f'#ifndef {cppvar}') or
+        line.startswith(f'#define {cppvar}') or
+        line.startswith(f'#endif  // {cppvar}')):
       is_header_guard = True
   # #include lines and header guards can be long, since there's no clean way to
   # split them.
@@ -4908,18 +4872,18 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
   # Doxygen documentation copying can get pretty long when using an overloaded
   # function declaration
   if (not line.startswith('#include') and not is_header_guard and
-      not Match(r'^\s*//.*http(s?)://\S*$', line) and
-      not Match(r'^\s*//\s*[^\s]*$', line) and
-      not Match(r'^// \$Id:.*#[0-9]+ \$$', line) and
-      not Match(r'^\s*/// [@\\](copydoc|copydetails|copybrief) .*$', line)):
+      not re.match(r'^\s*//.*http(s?)://\S*$', line) and
+      not re.match(r'^\s*//\s*[^\s]*$', line) and
+      not re.match(r'^// \$Id:.*#[0-9]+ \$$', line) and
+      not re.match(r'^\s*/// [@\\](copydoc|copydetails|copybrief) .*$', line)):
     line_width = GetLineWidth(line)
     if line_width > _line_length:
       error(filename, linenum, 'whitespace/line_length', 2,
-            'Lines should be <= %i characters long' % _line_length)
+            f'Lines should be <= {_line_length} characters long')
 
   if (cleansed_line.count(';') > 1 and
       # allow simple single line lambdas
-      not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}\n\r]*\}',
+      not re.match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}\n\r]*\}',
                 line) and
       # for loops are allowed two ;'s (and may run over two lines).
       cleansed_line.find('for') == -1 and
@@ -4978,9 +4942,9 @@ def _DropCommonSuffixes(filename):
     The filename with the common suffix removed.
   """
   for suffix in itertools.chain(
-      ('%s.%s' % (test_suffix.lstrip('_'), ext)
+      (f"{test_suffix.lstrip('_')}.{ext}"
        for test_suffix, ext in itertools.product(_test_suffixes, GetNonHeaderExtensions())),
-      ('%s.%s' % (suffix, ext)
+      (f'{suffix}.{ext}'
        for suffix, ext in itertools.product(['inl', 'imp', 'internal'], GetHeaderExtensions()))):
     if (filename.endswith(suffix) and len(filename) > len(suffix) and
         filename[-len(suffix) - 1] in ('-', '_')):
@@ -5022,11 +4986,11 @@ def _ClassifyInclude(fileinfo, include, used_angle_brackets, include_order="defa
   # Mark include as C header if in list or in a known folder for standard-ish C headers.
   is_std_c_header = (include_order == "default") or (include in _C_HEADERS
             # additional linux glibc header folders
-            or Search(r'(?:%s)\/.*\.h' % "|".join(C_STANDARD_HEADER_FOLDERS), include))
+            or re.search(rf'(?:{"|".join(C_STANDARD_HEADER_FOLDERS)})\/.*\.h', include))
 
   # Headers with C++ extensions shouldn't be considered C system headers
   include_ext = os.path.splitext(include)[1]
-  is_system = used_angle_brackets and not include_ext in ['.hh', '.hpp', '.hxx', '.h++']
+  is_system = used_angle_brackets and include_ext not in ['.hh', '.hpp', '.hxx', '.h++']
 
   if is_system:
     if is_cpp_header:
@@ -5088,7 +5052,7 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
   #
   # We also make an exception for Lua headers, which follow google
   # naming convention but not the include convention.
-  match = Match(r'#include\s*"([^/]+\.(.*))"', line)
+  match = re.match(r'#include\s*"([^/]+\.(.*))"', line)
   if match:
     if (IsHeaderExtension(match.group(2)) and
         not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1))):
@@ -5101,12 +5065,11 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
   match = _RE_PATTERN_INCLUDE.search(line)
   if match:
     include = match.group(2)
-    used_angle_brackets = (match.group(1) == '<')
+    used_angle_brackets = match.group(1) == '<'
     duplicate_line = include_state.FindHeader(include)
     if duplicate_line >= 0:
       error(filename, linenum, 'build/include', 4,
-            '"%s" already included at %s:%s' %
-            (include, filename, duplicate_line))
+            f'"{include}" already included at {filename}:{duplicate_line}')
       return
 
     for extension in GetNonHeaderExtensions():
@@ -5146,13 +5109,13 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
           _ClassifyInclude(fileinfo, include, used_angle_brackets, _include_order))
       if error_message:
         error(filename, linenum, 'build/include_order', 4,
-              '%s. Should be: %s.h, c system, c++ system, other.' %
-              (error_message, fileinfo.BaseName()))
+              f'{error_message}. Should be: {fileinfo.BaseName()}.h, c system,'
+              ' c++ system, other.')
       canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
       if not include_state.IsInAlphabeticalOrder(
           clean_lines, linenum, canonical_include):
         error(filename, linenum, 'build/include_alpha', 4,
-              'Include "%s" not in alphabetical order' % include)
+              f'Include "{include}" not in alphabetical order')
       include_state.SetLastHeader(canonical_include)
 
 
@@ -5182,7 +5145,7 @@ def _GetTextInside(text, start_pattern):
 
   # Give opening punctuations to get the matching close-punctuations.
   matching_punctuation = {'(': ')', '{': '}', '[': ']'}
-  closing_punctuation = set(itervalues(matching_punctuation))
+  closing_punctuation = set(dict.values(matching_punctuation))
 
   # Find the position to start extracting text.
   match = re.search(start_pattern, text, re.M)
@@ -5272,7 +5235,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
 
   # Reset include state across preprocessor directives.  This is meant
   # to silence warnings for conditional includes.
-  match = Match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
+  match = re.match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
   if match:
     include_state.ResetSection(match.group(1))
 
@@ -5292,15 +5255,15 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
 
   # Check if people are using the verboten C basic types.  The only exception
   # we regularly allow is "unsigned short port" for port.
-  if Search(r'\bshort port\b', line):
-    if not Search(r'\bunsigned short port\b', line):
+  if re.search(r'\bshort port\b', line):
+    if not re.search(r'\bunsigned short port\b', line):
       error(filename, linenum, 'runtime/int', 4,
             'Use "unsigned short" for ports, not "short"')
   else:
-    match = Search(r'\b(short|long(?! +double)|long long)\b', line)
+    match = re.search(r'\b(short|long(?! +double)|long long)\b', line)
     if match:
       error(filename, linenum, 'runtime/int', 4,
-            'Use int16/int64/etc, rather than the C type %s' % match.group(1))
+            f'Use int16/int64/etc, rather than the C type {match.group(1)}')
 
   # Check if some verboten operator overloading is going on
   # TODO(unknown): catch out-of-line unary operator&:
@@ -5308,13 +5271,13 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
   #   int operator&(const X& x) { return 42; }  // unary operator&
   # The trick is it's hard to tell apart from binary operator&:
   #   class Y { int operator&(const Y& x) { return 23; } }; // binary operator&
-  if Search(r'\boperator\s*&\s*\(\s*\)', line):
+  if re.search(r'\boperator\s*&\s*\(\s*\)', line):
     error(filename, linenum, 'runtime/operator', 4,
           'Unary operator& is dangerous.  Do not use it.')
 
   # Check for suspicious usage of "if" like
   # } if (a == b) {
-  if Search(r'\}\s*if\s*\(', line):
+  if re.search(r'\}\s*if\s*\(', line):
     error(filename, linenum, 'readability/braces', 4,
           'Did you mean "else if"? If not, start a new line for "if".')
 
@@ -5327,23 +5290,22 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
   #       boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line);
   printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(')
   if printf_args:
-    match = Match(r'([\w.\->()]+)$', printf_args)
+    match = re.match(r'([\w.\->()]+)$', printf_args)
     if match and match.group(1) != '__VA_ARGS__':
       function_name = re.search(r'\b((?:string)?printf)\s*\(',
                                 line, re.I).group(1)
       error(filename, linenum, 'runtime/printf', 4,
-            'Potential format string bug. Do %s("%%s", %s) instead.'
-            % (function_name, match.group(1)))
+            'Potential format string bug. Do'
+            f' {function_name}("%s", {match.group(1)}) instead.')
 
   # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
-  match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
-  if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
+  match = re.search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
+  if match and not re.match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
     error(filename, linenum, 'runtime/memset', 4,
-          'Did you mean "memset(%s, 0, %s)"?'
-          % (match.group(1), match.group(2)))
+          f'Did you mean "memset({match.group(1)}, 0, {match.group(2)})"?')
 
-  if Search(r'\busing namespace\b', line):
-    if Search(r'\bliterals\b', line):
+  if re.search(r'\busing namespace\b', line):
+    if re.search(r'\bliterals\b', line):
       error(filename, linenum, 'build/namespaces_literals', 5,
             'Do not use namespace using-directives.  '
             'Use using-declarations instead.')
@@ -5353,7 +5315,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
             'Use using-declarations instead.')
 
   # Detect variable-length arrays.
-  match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
+  match = re.match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
   if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
       match.group(3).find(']') == -1):
     # Split the size using space and arithmetic operators as delimiters.
@@ -5367,17 +5329,17 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
         skip_next = False
         continue
 
-      if Search(r'sizeof\(.+\)', tok): continue
-      if Search(r'arraysize\(\w+\)', tok): continue
+      if re.search(r'sizeof\(.+\)', tok): continue
+      if re.search(r'arraysize\(\w+\)', tok): continue
 
       tok = tok.lstrip('(')
       tok = tok.rstrip(')')
       if not tok: continue
-      if Match(r'\d+', tok): continue
-      if Match(r'0[xX][0-9a-fA-F]+', tok): continue
-      if Match(r'k[A-Z0-9]\w*', tok): continue
-      if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
-      if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
+      if re.match(r'\d+', tok): continue
+      if re.match(r'0[xX][0-9a-fA-F]+', tok): continue
+      if re.match(r'k[A-Z0-9]\w*', tok): continue
+      if re.match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
+      if re.match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
       # A catch all for tricky sizeof cases, including 'sizeof expression',
       # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
       # requires skipping the next token because we split on ' ' and '*'.
@@ -5395,7 +5357,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
   # macros are typically OK, so we allow use of "namespace {" on lines
   # that end with backslashes.
   if (IsHeaderExtension(file_extension)
-      and Search(r'\bnamespace\s*{', line)
+      and re.search(r'\bnamespace\s*{', line)
       and line[-1] != '\\'):
     error(filename, linenum, 'build/namespaces_headers', 4,
           'Do not use unnamed namespaces in header files.  See '
@@ -5415,7 +5377,7 @@ def CheckGlobalStatic(filename, clean_lines, linenum, error):
   line = clean_lines.elided[linenum]
 
   # Match two lines at a time to support multiline declarations
-  if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line):
+  if linenum + 1 < clean_lines.NumLines() and not re.search(r'[;({]', line):
     line += clean_lines.elided[linenum + 1].strip()
 
   # Check for people declaring static/global STL strings at the top level.
@@ -5424,7 +5386,7 @@ def CheckGlobalStatic(filename, clean_lines, linenum, error):
   # also because globals can be destroyed when some threads are still running.
   # TODO(unknown): Generalize this to also find static unique_ptr instances.
   # TODO(unknown): File bugs for clang-tidy to find these.
-  match = Match(
+  match = re.match(
       r'((?:|static +)(?:|const +))(?::*std::)?string( +const)? +'
       r'([a-zA-Z0-9_:]+)\b(.*)',
       line)
@@ -5446,20 +5408,19 @@ def CheckGlobalStatic(filename, clean_lines, linenum, error):
   #   matching identifiers.
   #    string Class::operator*()
   if (match and
-      not Search(r'\bstring\b(\s+const)?\s*[\*\&]\s*(const\s+)?\w', line) and
-      not Search(r'\boperator\W', line) and
-      not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(4))):
-    if Search(r'\bconst\b', line):
+      not re.search(r'\bstring\b(\s+const)?\s*[\*\&]\s*(const\s+)?\w', line) and
+      not re.search(r'\boperator\W', line) and
+      not re.match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(4))):
+    if re.search(r'\bconst\b', line):
       error(filename, linenum, 'runtime/string', 4,
-            'For a static/global string constant, use a C style string '
-            'instead: "%schar%s %s[]".' %
-            (match.group(1), match.group(2) or '', match.group(3)))
+            'For a static/global string constant, use a C style string instead:'
+            f' "{match.group(1)}char{match.group(2) or ""} {match.group(3)}[]".')
     else:
       error(filename, linenum, 'runtime/string', 4,
             'Static/global string variables are not permitted.')
 
-  if (Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line) or
-      Search(r'\b([A-Za-z0-9_]*_)\(CHECK_NOTNULL\(\1\)\)', line)):
+  if (re.search(r'\b([A-Za-z0-9_]*_)\(\1\)', line) or
+      re.search(r'\b([A-Za-z0-9_]*_)\(CHECK_NOTNULL\(\1\)\)', line)):
     error(filename, linenum, 'runtime/init', 4,
           'You seem to be initializing a member variable with itself.')
 
@@ -5476,21 +5437,21 @@ def CheckPrintf(filename, clean_lines, linenum, error):
   line = clean_lines.elided[linenum]
 
   # When snprintf is used, the second argument shouldn't be a literal.
-  match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
+  match = re.search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
   if match and match.group(2) != '0':
     # If 2nd arg is zero, snprintf is used to calculate size.
-    error(filename, linenum, 'runtime/printf', 3,
-          'If you can, use sizeof(%s) instead of %s as the 2nd arg '
-          'to snprintf.' % (match.group(1), match.group(2)))
+    error(filename, linenum, 'runtime/printf', 3, 'If you can, use'
+          f' sizeof({match.group(1)}) instead of {match.group(2)}'
+          ' as the 2nd arg to snprintf.')
 
   # Check if some verboten C functions are being used.
-  if Search(r'\bsprintf\s*\(', line):
+  if re.search(r'\bsprintf\s*\(', line):
     error(filename, linenum, 'runtime/printf', 5,
           'Never use sprintf. Use snprintf instead.')
-  match = Search(r'\b(strcpy|strcat)\s*\(', line)
+  match = re.search(r'\b(strcpy|strcat)\s*\(', line)
   if match:
     error(filename, linenum, 'runtime/printf', 4,
-          'Almost always, snprintf is better than %s' % match.group(1))
+          f'Almost always, snprintf is better than {match.group(1)}')
 
 
 def IsDerivedFunction(clean_lines, linenum):
@@ -5504,14 +5465,14 @@ def IsDerivedFunction(clean_lines, linenum):
     virt-specifier.
   """
   # Scan back a few lines for start of current function
-  for i in xrange(linenum, max(-1, linenum - 10), -1):
-    match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i])
+  for i in range(linenum, max(-1, linenum - 10), -1):
+    match = re.match(r'^([^()]*\w+)\(', clean_lines.elided[i])
     if match:
       # Look for "override" after the matching closing parenthesis
       line, _, closing_paren = CloseExpression(
           clean_lines, i, len(match.group(1)))
       return (closing_paren >= 0 and
-              Search(r'\boverride\b', line[closing_paren:]))
+              re.search(r'\boverride\b', line[closing_paren:]))
   return False
 
 
@@ -5525,9 +5486,9 @@ def IsOutOfLineMethodDefinition(clean_lines, linenum):
     True if current line contains an out-of-line method definition.
   """
   # Scan back a few lines for start of current function
-  for i in xrange(linenum, max(-1, linenum - 10), -1):
-    if Match(r'^([^()]*\w+)\(', clean_lines.elided[i]):
-      return Match(r'^[^()]*\w+::\w+\(', clean_lines.elided[i]) is not None
+  for i in range(linenum, max(-1, linenum - 10), -1):
+    if re.match(r'^([^()]*\w+)\(', clean_lines.elided[i]):
+      return re.match(r'^[^()]*\w+::\w+\(', clean_lines.elided[i]) is not None
   return False
 
 
@@ -5541,24 +5502,24 @@ def IsInitializerList(clean_lines, linenum):
     True if current line appears to be inside constructor initializer
     list, False otherwise.
   """
-  for i in xrange(linenum, 1, -1):
+  for i in range(linenum, 1, -1):
     line = clean_lines.elided[i]
     if i == linenum:
-      remove_function_body = Match(r'^(.*)\{\s*$', line)
+      remove_function_body = re.match(r'^(.*)\{\s*$', line)
       if remove_function_body:
         line = remove_function_body.group(1)
 
-    if Search(r'\s:\s*\w+[({]', line):
+    if re.search(r'\s:\s*\w+[({]', line):
       # A lone colon tend to indicate the start of a constructor
       # initializer list.  It could also be a ternary operator, which
       # also tend to appear in constructor initializer lists as
       # opposed to parameter lists.
       return True
-    if Search(r'\}\s*,\s*$', line):
+    if re.search(r'\}\s*,\s*$', line):
       # A closing brace followed by a comma is probably the end of a
       # brace-initialized member in constructor initializer list.
       return True
-    if Search(r'[{};]\s*$', line):
+    if re.search(r'[{};]\s*$', line):
       # Found one of the following:
       # - A closing brace or semicolon, probably the end of the previous
       #   function.
@@ -5622,13 +5583,13 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
   # that spans more than 2 lines, please use a typedef.
   if linenum > 1:
     previous = None
-    if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
+    if re.match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
       # previous_line\n + ::current_line
-      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
+      previous = re.search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
                         clean_lines.elided[linenum - 1])
-    elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
+    elif re.match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
       # previous_line::\n + current_line
-      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
+      previous = re.search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
                         clean_lines.elided[linenum - 1])
     if previous:
       line = previous.group(1) + line.lstrip()
@@ -5642,7 +5603,7 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
           # Found the matching < on an earlier line, collect all
           # pieces up to current line.
           line = ''
-          for i in xrange(startline, linenum + 1):
+          for i in range(startline, linenum + 1):
             line += clean_lines.elided[i].strip()
 
   # Check for non-const references in function parameters.  A single '&' may
@@ -5666,15 +5627,15 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
   # appear inside the second set of parentheses on the current line as
   # opposed to the first set.
   if linenum > 0:
-    for i in xrange(linenum - 1, max(0, linenum - 10), -1):
+    for i in range(linenum - 1, max(0, linenum - 10), -1):
       previous_line = clean_lines.elided[i]
-      if not Search(r'[),]\s*$', previous_line):
+      if not re.search(r'[),]\s*$', previous_line):
         break
-      if Match(r'^\s*:\s+\S', previous_line):
+      if re.match(r'^\s*:\s+\S', previous_line):
         return
 
   # Avoid preprocessors
-  if Search(r'\\\s*$', line):
+  if re.search(r'\\\s*$', line):
     return
 
   # Avoid constructor initializer lists
@@ -5691,25 +5652,25 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
                            r'operator\s*[<>][<>]|'
                            r'static_assert|COMPILE_ASSERT'
                            r')\s*\(')
-  if Search(allowed_functions, line):
+  if re.search(allowed_functions, line):
     return
-  elif not Search(r'\S+\([^)]*$', line):
+  elif not re.search(r'\S+\([^)]*$', line):
     # Don't see an allowed function on this line.  Actually we
     # didn't see any function name on this line, so this is likely a
     # multi-line parameter list.  Try a bit harder to catch this case.
-    for i in xrange(2):
+    for i in range(2):
       if (linenum > i and
-          Search(allowed_functions, clean_lines.elided[linenum - i - 1])):
+          re.search(allowed_functions, clean_lines.elided[linenum - i - 1])):
         return
 
-  decls = ReplaceAll(r'{[^}]*}', ' ', line)  # exclude function body
+  decls = re.sub(r'{[^}]*}', ' ', line)  # exclude function body
   for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
-    if (not Match(_RE_PATTERN_CONST_REF_PARAM, parameter) and
-        not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)):
+    if (not re.match(_RE_PATTERN_CONST_REF_PARAM, parameter) and
+        not re.match(_RE_PATTERN_REF_STREAM_PARAM, parameter)):
       error(filename, linenum, 'runtime/references', 2,
             'Is this a non-const reference? '
             'If so, make const or use a pointer: ' +
-            ReplaceAll(' *<', '<', parameter))
+            re.sub(' *<', '<', parameter))
 
 
 def CheckCasts(filename, clean_lines, linenum, error):
@@ -5727,7 +5688,7 @@ def CheckCasts(filename, clean_lines, linenum, error):
   # I just try to capture the most common basic types, though there are more.
   # Parameterless conversion functions, such as bool(), are allowed as they are
   # probably a member operator declaration or default constructor.
-  match = Search(
+  match = re.search(
       r'(\bnew\s+(?:const\s+)?|\S<\s*(?:const\s+)?)?\b'
       r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
       r'(\([^)].*)', line)
@@ -5751,7 +5712,7 @@ def CheckCasts(filename, clean_lines, linenum, error):
 
     # Avoid arrays by looking for brackets that come after the closing
     # parenthesis.
-    if Match(r'\([^()]+\)\s*\[', match.group(3)):
+    if re.match(r'\([^()]+\)\s*\[', match.group(3)):
       return
 
     # Other things to ignore:
@@ -5762,15 +5723,14 @@ def CheckCasts(filename, clean_lines, linenum, error):
     matched_funcptr = match.group(3)
     if (matched_new_or_template is None and
         not (matched_funcptr and
-             (Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
+             (re.match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
                     matched_funcptr) or
               matched_funcptr.startswith('(*)'))) and
-        not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and
-        not Search(r'new\(\S+\)\s*' + matched_type, line)):
+        not re.match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and
+        not re.search(r'new\(\S+\)\s*' + matched_type, line)):
       error(filename, linenum, 'readability/casting', 4,
             'Using deprecated casting style.  '
-            'Use static_cast<%s>(...) instead' %
-            matched_type)
+            f'Use static_cast<{matched_type}>(...) instead')
 
   if not expecting_function:
     CheckCStyleCast(filename, clean_lines, linenum, 'static_cast',
@@ -5799,7 +5759,7 @@ def CheckCasts(filename, clean_lines, linenum, error):
   #
   # This is not a cast:
   #   reference_type&(int* function_param);
-  match = Search(
+  match = re.search(
       r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|'
       r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line)
   if match:
@@ -5807,7 +5767,7 @@ def CheckCasts(filename, clean_lines, linenum, error):
     # dereferenced by the casted pointer, as opposed to the casted
     # pointer itself.
     parenthesis_error = False
-    match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
+    match = re.match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
     if match:
       _, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1)))
       if x1 >= 0 and clean_lines.elided[y1][x1] == '(':
@@ -5816,7 +5776,7 @@ def CheckCasts(filename, clean_lines, linenum, error):
           extended_line = clean_lines.elided[y2][x2:]
           if y2 < clean_lines.NumLines() - 1:
             extended_line += clean_lines.elided[y2 + 1]
-          if Match(r'\s*(?:->|\[)', extended_line):
+          if re.match(r'\s*(?:->|\[)', extended_line):
             parenthesis_error = True
 
     if parenthesis_error:
@@ -5848,21 +5808,21 @@ def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
     False otherwise.
   """
   line = clean_lines.elided[linenum]
-  match = Search(pattern, line)
+  match = re.search(pattern, line)
   if not match:
     return False
 
   # Exclude lines with keywords that tend to look like casts
   context = line[0:match.start(1) - 1]
-  if Match(r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
+  if re.match(r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
     return False
 
   # Try expanding current context to see if we one level of
   # parentheses inside a macro.
   if linenum > 0:
-    for i in xrange(linenum - 1, max(0, linenum - 5), -1):
+    for i in range(linenum - 1, max(0, linenum - 5), -1):
       context = clean_lines.elided[i] + context
-  if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
+  if re.match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
     return False
 
   # operator++(int) and operator--(int)
@@ -5873,14 +5833,13 @@ def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
   # A single unnamed argument for a function tends to look like old style cast.
   # If we see those, don't issue warnings for deprecated casts.
   remainder = line[match.end(0):]
-  if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
+  if re.match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
            remainder):
     return False
 
   # At this point, all that should be left is actual casts.
   error(filename, linenum, 'readability/casting', 4,
-        'Using C-style cast.  Use %s<%s>(...) instead' %
-        (cast_type, match.group(1)))
+        f'Using C-style cast.  Use {cast_type}<{match.group(1)}>(...) instead')
 
   return True
 
@@ -5897,13 +5856,13 @@ def ExpectingFunctionArgs(clean_lines, linenum):
     of function types.
   """
   line = clean_lines.elided[linenum]
-  return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
+  return (re.match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
           (linenum >= 2 and
-           (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
+           (re.match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
                   clean_lines.elided[linenum - 1]) or
-            Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
+            re.match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
                   clean_lines.elided[linenum - 2]) or
-            Search(r'\bstd::m?function\s*\<\s*$',
+            re.search(r'\bstd::m?function\s*\<\s*$',
                    clean_lines.elided[linenum - 1]))))
 
 
@@ -5955,7 +5914,26 @@ _HEADERS_MAYBE_TEMPLATES = (
     ('<utility>', ('forward', 'make_pair', 'move', 'swap')),
     )
 
-_RE_PATTERN_STRING = re.compile(r'\bstring\b')
+# Non templated types or global objects
+_HEADERS_TYPES_OR_OBJS = (
+    # String and others are special -- it is a non-templatized type in STL.
+    ('<string>', ('string',)),
+    ('<iostream>', ('cin', 'cout', 'cerr', 'clog', 'wcin', 'wcout',
+                    'wcerr', 'wclog')),
+    ('<cstdio>', ('FILE', 'fpos_t')))
+
+# Non templated functions
+_HEADERS_FUNCTIONS = (
+    ('<cstdio>', ('fopen', 'freopen',
+                  'fclose', 'fflush', 'setbuf', 'setvbuf', 'fread',
+                  'fwrite', 'fgetc', 'getc', 'fgets', 'fputc', 'putc',
+                  'fputs', 'getchar', 'gets', 'putchar', 'puts', 'ungetc',
+                  'scanf', 'fscanf', 'sscanf', 'vscanf', 'vfscanf',
+                  'vsscanf', 'printf', 'fprintf', 'sprintf', 'snprintf',
+                  'vprintf', 'vfprintf', 'vsprintf', 'vsnprintf',
+                  'ftell', 'fgetpos', 'fseek', 'fsetpos',
+                  'clearerr', 'feof', 'ferror', 'perror',
+                  'tmpfile', 'tmpnam'),),)
 
 _re_pattern_headers_maybe_templates = []
 for _header, _templates in _HEADERS_MAYBE_TEMPLATES:
@@ -5986,6 +5964,23 @@ for _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
          _template + '<>',
          _header))
 
+_re_pattern_types_or_objs = []
+for _header, _types_or_objs in _HEADERS_TYPES_OR_OBJS:
+  for _type_or_obj in _types_or_objs:
+    _re_pattern_types_or_objs.append(
+        (re.compile(r'\b' + _type_or_obj + r'\b'),
+            _type_or_obj,
+            _header))
+
+_re_pattern_functions = []
+for _header, _functions in _HEADERS_FUNCTIONS:
+  for _function in _functions:
+    # Match printf(..., ...), but not foo->printf, foo.printf or
+    # 'type::printf()'.
+    _re_pattern_functions.append(
+        (re.compile(r'([^>.]|^)\b' + _function + r'\([^\)]'),
+            _function,
+            _header))
 
 def FilesBelongToSameModule(filename_cc, filename_h):
   """Check if these two filenames belong to the same module.
@@ -6017,7 +6012,7 @@ def FilesBelongToSameModule(filename_cc, filename_h):
     string: the additional prefix needed to open the header file.
   """
   fileinfo_cc = FileInfo(filename_cc)
-  if not fileinfo_cc.Extension().lstrip('.') in GetNonHeaderExtensions():
+  if fileinfo_cc.Extension().lstrip('.') not in GetNonHeaderExtensions():
     return (False, '')
 
   fileinfo_h = FileInfo(filename_h)
@@ -6025,7 +6020,7 @@ def FilesBelongToSameModule(filename_cc, filename_h):
     return (False, '')
 
   filename_cc = filename_cc[:-(len(fileinfo_cc.Extension()))]
-  matched_test_suffix = Search(_TEST_FILE_SUFFIX, fileinfo_cc.BaseName())
+  matched_test_suffix = re.search(_TEST_FILE_SUFFIX, fileinfo_cc.BaseName())
   if matched_test_suffix:
     filename_cc = filename_cc[:-len(matched_test_suffix.group(1))]
 
@@ -6045,34 +6040,6 @@ def FilesBelongToSameModule(filename_cc, filename_h):
   return files_belong_to_same_module, common_path
 
 
-def UpdateIncludeState(filename, include_dict, io=codecs):
-  """Fill up the include_dict with new includes found from the file.
-
-  Args:
-    filename: the name of the header to read.
-    include_dict: a dictionary in which the headers are inserted.
-    io: The io factory to use to read the file. Provided for testability.
-
-  Returns:
-    True if a header was successfully added. False otherwise.
-  """
-  headerfile = None
-  try:
-    with io.open(filename, 'r', 'utf8', 'replace') as headerfile:
-      linenum = 0
-      for line in headerfile:
-        linenum += 1
-        clean_line = CleanseComments(line)
-        match = _RE_PATTERN_INCLUDE.search(clean_line)
-        if match:
-          include = match.group(2)
-          include_dict.setdefault(include, linenum)
-    return True
-  except IOError:
-    return False
-
-
-
 def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
                               io=codecs):
   """Reports for missing stl includes.
@@ -6094,26 +6061,29 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
   required = {}  # A map of header name to linenumber and the template entity.
                  # Example of required: { '<functional>': (1219, 'less<>') }
 
-  for linenum in xrange(clean_lines.NumLines()):
+  for linenum in range(clean_lines.NumLines()):
     line = clean_lines.elided[linenum]
     if not line or line[0] == '#':
       continue
 
-    # String is special -- it is a non-templatized type in STL.
-    matched = _RE_PATTERN_STRING.search(line)
-    if matched:
-      # Don't warn about strings in non-STL namespaces:
-      # (We check only the first match per line; good enough.)
-      prefix = line[:matched.start()]
-      if prefix.endswith('std::') or not prefix.endswith('::'):
-        required['<string>'] = (linenum, 'string')
+    _re_patterns = []
+    _re_patterns.extend(_re_pattern_types_or_objs)
+    _re_patterns.extend(_re_pattern_functions)
+    for pattern, item, header in _re_patterns:
+      matched = pattern.search(line)
+      if matched:
+        # Don't warn about strings in non-STL namespaces:
+        # (We check only the first match per line; good enough.)
+        prefix = line[:matched.start()]
+        if prefix.endswith('std::') or not prefix.endswith('::'):
+          required[header] = (linenum, item)
 
     for pattern, template, header in _re_pattern_headers_maybe_templates:
       if pattern.search(line):
         required[header] = (linenum, template)
 
     # The following function is just a speed up, no semantics are changed.
-    if not '<' in line:  # Reduces the cpu time usage by skipping lines.
+    if '<' not in line:  # Reduces the cpu time usage by skipping lines.
       continue
 
     for pattern, template, header in _re_pattern_templates:
@@ -6125,46 +6095,10 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
         if prefix.endswith('std::') or not prefix.endswith('::'):
           required[header] = (linenum, template)
 
-  # The policy is that if you #include something in foo.h you don't need to
-  # include it again in foo.cc. Here, we will look at possible includes.
   # Let's flatten the include_state include_list and copy it into a dictionary.
   include_dict = dict([item for sublist in include_state.include_list
                        for item in sublist])
 
-  # Did we find the header for this file (if any) and successfully load it?
-  header_found = False
-
-  # Use the absolute path so that matching works properly.
-  abs_filename = FileInfo(filename).FullName()
-
-  # For Emacs's flymake.
-  # If cpplint is invoked from Emacs's flymake, a temporary file is generated
-  # by flymake and that file name might end with '_flymake.cc'. In that case,
-  # restore original file name here so that the corresponding header file can be
-  # found.
-  # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
-  # instead of 'foo_flymake.h'
-  abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)
-
-  # include_dict is modified during iteration, so we iterate over a copy of
-  # the keys.
-  header_keys = list(include_dict.keys())
-  for header in header_keys:
-    (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
-    fullpath = common_path + header
-    if same_module and UpdateIncludeState(fullpath, include_dict, io):
-      header_found = True
-
-  # If we can't find the header file for a .cc, assume it's because we don't
-  # know where to look. In that case we'll give up as we're not sure they
-  # didn't include it in the .h file.
-  # TODO(unknown): Do a better job of finding .h files so we are confident that
-  # not having the .h file means there isn't one.
-  if not header_found:
-    for extension in GetNonHeaderExtensions():
-      if filename.endswith('.' + extension):
-        return
-
   # All the lines have been processed, report the errors found.
   for required_header_unstripped in sorted(required, key=required.__getitem__):
     template = required[required_header_unstripped][1]
@@ -6209,20 +6143,20 @@ def CheckRedundantVirtual(filename, clean_lines, linenum, error):
   """
   # Look for "virtual" on current line.
   line = clean_lines.elided[linenum]
-  virtual = Match(r'^(.*)(\bvirtual\b)(.*)$', line)
+  virtual = re.match(r'^(.*)(\bvirtual\b)(.*)$', line)
   if not virtual: return
 
   # Ignore "virtual" keywords that are near access-specifiers.  These
   # are only used in class base-specifier and do not apply to member
   # functions.
-  if (Search(r'\b(public|protected|private)\s+$', virtual.group(1)) or
-      Match(r'^\s+(public|protected|private)\b', virtual.group(3))):
+  if (re.search(r'\b(public|protected|private)\s+$', virtual.group(1)) or
+      re.match(r'^\s+(public|protected|private)\b', virtual.group(3))):
     return
 
   # Ignore the "virtual" keyword from virtual base classes.  Usually
   # there is a column on the same line in these cases (virtual base
   # classes are rare in google3 because multiple inheritance is rare).
-  if Match(r'^.*[^:]:[^:].*$', line): return
+  if re.match(r'^.*[^:]:[^:].*$', line): return
 
   # Look for the next opening parenthesis.  This is the start of the
   # parameter list (possibly on the next line shortly after virtual).
@@ -6232,9 +6166,9 @@ def CheckRedundantVirtual(filename, clean_lines, linenum, error):
   end_col = -1
   end_line = -1
   start_col = len(virtual.group(2))
-  for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())):
+  for start_line in range(linenum, min(linenum + 3, clean_lines.NumLines())):
     line = clean_lines.elided[start_line][start_col:]
-    parameter_list = Match(r'^([^(]*)\(', line)
+    parameter_list = re.match(r'^([^(]*)\(', line)
     if parameter_list:
       # Match parentheses to find the end of the parameter list
       (_, end_line, end_col) = CloseExpression(
@@ -6247,18 +6181,18 @@ def CheckRedundantVirtual(filename, clean_lines, linenum, error):
 
   # Look for "override" or "final" after the parameter list
   # (possibly on the next few lines).
-  for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())):
+  for i in range(end_line, min(end_line + 3, clean_lines.NumLines())):
     line = clean_lines.elided[i][end_col:]
-    match = Search(r'\b(override|final)\b', line)
+    match = re.search(r'\b(override|final)\b', line)
     if match:
       error(filename, linenum, 'readability/inheritance', 4,
             ('"virtual" is redundant since function is '
-             'already declared as "%s"' % match.group(1)))
+            f'already declared as "{match.group(1)}"'))
 
     # Set end_col to check whole lines after we are done with the
     # first line.
     end_col = 0
-    if Search(r'[^\w]\s*$', line):
+    if re.search(r'[^\w]\s*$', line):
       break
 
 
@@ -6285,7 +6219,7 @@ def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error):
       return
 
   # Check that at most one of "override" or "final" is present, not both
-  if Search(r'\boverride\b', fragment) and Search(r'\bfinal\b', fragment):
+  if re.search(r'\boverride\b', fragment) and re.search(r'\bfinal\b', fragment):
     error(filename, linenum, 'readability/inheritance', 4,
           ('"override" is redundant since function is '
            'already declared as "final"'))
@@ -6350,7 +6284,7 @@ def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
 def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum,
                                     error):
   line = raw_lines_no_comments[linenum]
-  if Match(r'^\s+', line):
+  if re.match(r'^\s+', line):
     error(filename, linenum, 'runtime/indentation_namespace', 4,
           'Do not indent within a namespace')
 
@@ -6411,13 +6345,15 @@ def FlagCxx11Features(filename, clean_lines, linenum, error):
   """
   line = clean_lines.elided[linenum]
 
-  include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
+  include = re.match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
 
   # Flag unapproved C++ TR1 headers.
   if include and include.group(1).startswith('tr1/'):
     error(filename, linenum, 'build/c++tr1', 5,
-          ('C++ TR1 headers such as <%s> are unapproved.') % include.group(1))
+          f"C++ TR1 headers such as <{include.group(1)}> are unapproved.")
 
+  # TODO: Figure out which of these headers are actually forbidden
+  # and add <filesystem> somewhere from C++17
   # Flag unapproved C++11 headers.
   if include and include.group(1) in ('cfenv',
                                       'condition_variable',
@@ -6431,11 +6367,11 @@ def FlagCxx11Features(filename, clean_lines, linenum, error):
                                       'system_error',
                                      ):
     error(filename, linenum, 'build/c++11', 5,
-          ('<%s> is an unapproved C++11 header.') % include.group(1))
+          f"<{include.group(1)}> is an unapproved C++11 header.")
 
   # The only place where we need to worry about C++11 keywords and library
   # features in preprocessor directives is in macro definitions.
-  if Match(r'\s*#', line) and not Match(r'\s*#\s*define\b', line): return
+  if re.match(r'\s*#', line) and not re.match(r'\s*#\s*define\b', line): return
 
   # These are classes and free functions.  The classes are always
   # mentioned as std::*, but we only catch the free functions if
@@ -6445,11 +6381,11 @@ def FlagCxx11Features(filename, clean_lines, linenum, error):
       'alignment_of',
       'aligned_union',
       ):
-    if Search(r'\bstd::%s\b' % top_name, line):
+    if re.search(rf'\bstd::{top_name}\b', line):
       error(filename, linenum, 'build/c++11', 5,
-            ('std::%s is an unapproved C++11 class or function.  Send c-style '
-             'an example of where it would make your code more readable, and '
-             'they may let you use it.') % top_name)
+            (f'std::{top_name} is an unapproved C++11 class or function.  '
+             'Send c-style an example of where it would'
+             ' make your code more readable, and they may let you use it.'))
 
 
 def FlagCxx14Features(filename, clean_lines, linenum, error):
@@ -6463,12 +6399,12 @@ def FlagCxx14Features(filename, clean_lines, linenum, error):
   """
   line = clean_lines.elided[linenum]
 
-  include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
+  include = re.match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
 
   # Flag unapproved C++14 headers.
   if include and include.group(1) in ('scoped_allocator', 'shared_mutex'):
     error(filename, linenum, 'build/c++14', 5,
-          ('<%s> is an unapproved C++14 header.') % include.group(1))
+          f"<{include.group(1)}> is an unapproved C++14 header.")
 
 
 def ProcessFileData(filename, file_extension, lines, error,
@@ -6503,7 +6439,7 @@ def ProcessFileData(filename, file_extension, lines, error,
   if IsHeaderExtension(file_extension):
     CheckForHeaderGuard(filename, clean_lines, error)
 
-  for line in xrange(clean_lines.NumLines()):
+  for line in range(clean_lines.NumLines()):
     ProcessLine(filename, file_extension, clean_lines, line,
                 include_state, function_state, nesting_state, error,
                 extra_check_functions)
@@ -6572,10 +6508,10 @@ def ProcessConfigOverrides(filename):
                 if _cpplint_state.quiet:
                   # Suppress "Ignoring file" warning when using --quiet.
                   return False
-                _cpplint_state.PrintInfo('Ignoring "%s": file excluded by "%s". '
+                _cpplint_state.PrintInfo(f'Ignoring "{filename}": file excluded by "{cfg_file}". '
                                  'File path component "%s" matches '
                                  'pattern "%s"\n' %
-                                 (filename, cfg_file, base_name, val))
+                                 (base_name, val))
                 return False
           elif name == 'linelength':
             global _line_length
@@ -6595,12 +6531,11 @@ def ProcessConfigOverrides(filename):
             ProcessIncludeOrderOption(val)
           else:
             _cpplint_state.PrintError(
-                'Invalid configuration option (%s) in file %s\n' %
-                (name, cfg_file))
+                f'Invalid configuration option ({name}) in file {cfg_file}\n')
 
     except IOError:
       _cpplint_state.PrintError(
-          "Skipping config file '%s': Can't open for reading\n" % cfg_file)
+          f"Skipping config file '{cfg_file}': Can't open for reading\n")
       keep_looking = False
 
   # Apply all the accumulated filters in reverse order (top-level directory
@@ -6662,8 +6597,9 @@ def ProcessFile(filename, vlevel, extra_check_functions=None):
         lf_lines.append(linenum + 1)
 
   except IOError:
+    # TODO: Maybe make this have an exit code of 2 after all is done
     _cpplint_state.PrintError(
-        "Skipping input '%s': Can't open for reading\n" % filename)
+        f"Skipping input '{filename}': Can't open for reading\n")
     _RestoreFilters()
     return
 
@@ -6673,8 +6609,8 @@ def ProcessFile(filename, vlevel, extra_check_functions=None):
   # When reading from stdin, the extension is unknown, so no cpplint tests
   # should rely on the extension.
   if filename != '-' and file_extension not in GetAllExtensions():
-    _cpplint_state.PrintError('Ignoring %s; not a valid file name '
-                     '(%s)\n' % (filename, ', '.join(GetAllExtensions())))
+    _cpplint_state.PrintError(f'Ignoring {filename}; not a valid file name'
+                              f' ({(", ".join(GetAllExtensions()))})\n')
   else:
     ProcessFileData(filename, file_extension, lines, Error,
                     extra_check_functions)
@@ -6700,7 +6636,7 @@ def ProcessFile(filename, vlevel, extra_check_functions=None):
   # Suppress printing anything if --quiet was passed unless the error
   # count has increased after processing this file.
   if not _cpplint_state.quiet or old_errors != _cpplint_state.error_count:
-    _cpplint_state.PrintInfo('Done processing %s\n' % filename)
+    _cpplint_state.PrintInfo(f'Done processing {filename}\n')
   _RestoreFilters()
 
 
@@ -6731,7 +6667,7 @@ def PrintCategories():
 
   These are the categories used to filter messages via --filter.
   """
-  sys.stderr.write(''.join('  %s\n' % cat for cat in _ERROR_CATEGORIES))
+  sys.stderr.write(''.join(f'  {cat}\n' for cat in _ERROR_CATEGORIES))
   sys.exit(0)
 
 
diff --git a/dev-requirements b/dev-requirements
index ded66ac..d5ab56a 100644
--- a/dev-requirements
+++ b/dev-requirements
@@ -4,6 +4,7 @@
 flake8>=4.0.1
 flake8-polyfill
 pylint>=2.11.0
-tox>=3.0.0,<4.0.0
-tox-pyenv
+tox<5.0.0
+tox-gh-actions<4.0.0
 importlib-metadata>=0.12
+setuptools==58.2.0
diff --git a/samples/chromium-sample/simple.def b/samples/chromium-sample/simple.def
index d1c4a68..6d0351d 100644
--- a/samples/chromium-sample/simple.def
+++ b/samples/chromium-sample/simple.def
@@ -5,11 +5,15 @@ Done processing src/chrome_content_renderer_client.cc
 Done processing src/chrome_content_renderer_client.h
 Done processing src/io_thread.cc
 Done processing src/io_thread.h
-Total errors found: 13
+Total errors found: 21
 
 src/chrome_content_renderer_client.cc:113:  Include the directory when naming header files  [build/include_subdir] [4]
 src/chrome_content_renderer_client.cc:1156:  Use int16/int64/etc, rather than the C type long  [runtime/int] [4]
 src/chrome_content_renderer_client.cc:1161:  Use int16/int64/etc, rather than the C type long  [runtime/int] [4]
+src/chrome_content_renderer_client.cc:1203:  Add #include <set> for set<>  [build/include_what_you_use] [4]
+src/chrome_content_renderer_client.cc:1245:  Add #include <vector> for vector<>  [build/include_what_you_use] [4]
+src/chrome_content_renderer_client.cc:1359:  Add #include <map> for map<>  [build/include_what_you_use] [4]
+src/chrome_content_renderer_client.cc:1366:  Add #include <string> for string  [build/include_what_you_use] [4]
 src/chrome_content_renderer_client.cc:5:  samples/chromium-sample/src/chrome_content_renderer_client.cc should include its header file samples/chromium-sample/src/chrome_content_renderer_client.h  [build/include] [5]
 src/chrome_content_renderer_client.h:5:  #ifndef header guard has wrong style, please use: SAMPLES_CHROMIUM_SAMPLE_SRC_CHROME_CONTENT_RENDERER_CLIENT_H_  [build/header_guard] [5]
 src/chrome_content_renderer_client.h:225:  #endif line should be "#endif  // SAMPLES_CHROMIUM_SAMPLE_SRC_CHROME_CONTENT_RENDERER_CLIENT_H_"  [build/header_guard] [5]
@@ -17,6 +21,10 @@ src/chrome_content_renderer_client.h:115:  Use int16/int64/etc, rather than the
 src/chrome_content_renderer_client.h:117:  Use int16/int64/etc, rather than the C type long  [runtime/int] [4]
 src/io_thread.cc:1148:  Closing ) should be moved to the previous line  [whitespace/parens] [2]
 src/io_thread.cc:1547:  Missing space around colon in range-based for loop  [whitespace/forcolon] [2]
+src/io_thread.cc:651:  Add #include <map> for map<>  [build/include_what_you_use] [4]
+src/io_thread.cc:1546:  Add #include <unordered_set> for unordered_set<>  [build/include_what_you_use] [4]
+src/io_thread.cc:1609:  Add #include <string> for string  [build/include_what_you_use] [4]
+src/io_thread.cc:1731:  Add #include <memory> for unique_ptr<>  [build/include_what_you_use] [4]
 src/io_thread.cc:5:  samples/chromium-sample/src/io_thread.cc should include its header file samples/chromium-sample/src/io_thread.h  [build/include] [5]
 src/io_thread.h:5:  #ifndef header guard has wrong style, please use: SAMPLES_CHROMIUM_SAMPLE_SRC_IO_THREAD_H_  [build/header_guard] [5]
 src/io_thread.h:565:  #endif line should be "#endif  // SAMPLES_CHROMIUM_SAMPLE_SRC_IO_THREAD_H_"  [build/header_guard] [5]
diff --git a/samples/codelite-sample/simple.def b/samples/codelite-sample/simple.def
index 4e45c6b..88c9bf0 100644
--- a/samples/codelite-sample/simple.def
+++ b/samples/codelite-sample/simple.def
@@ -3,7 +3,7 @@ src/*
 4
 Done processing src/pptable.cpp
 Done processing src/pptable.h
-Total errors found: 681
+Total errors found: 685
 
 src/pptable.cpp:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/pptable.cpp:1:  Include the directory when naming header files  [build/include_subdir] [4]
@@ -605,6 +605,10 @@ src/pptable.cpp:660:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/pptable.cpp:661:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/pptable.cpp:662:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/pptable.cpp:663:  Tab found; better to use spaces  [whitespace/tab] [1]
+src/pptable.cpp:526:  Add #include <map> for map<>  [build/include_what_you_use] [4]
+src/pptable.cpp:592:  Add #include <vector> for vector<>  [build/include_what_you_use] [4]
+src/pptable.cpp:602:  Add #include <cstdio> for sprintf  [build/include_what_you_use] [4]
+src/pptable.cpp:648:  Add #include <string> for string  [build/include_what_you_use] [4]
 src/pptable.h:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/pptable.h:1:  #ifndef header guard has wrong style, please use: SAMPLES_CODELITE_SAMPLE_SRC_PPTABLE_H_  [build/header_guard] [5]
 src/pptable.h:131:  #endif line should be "#endif  // SAMPLES_CODELITE_SAMPLE_SRC_PPTABLE_H_"  [build/header_guard] [5]
diff --git a/samples/protobuf-sample/simple.def b/samples/protobuf-sample/simple.def
index 6135da6..393995b 100644
--- a/samples/protobuf-sample/simple.def
+++ b/samples/protobuf-sample/simple.def
@@ -4,7 +4,7 @@ src/*
 Done processing src/descriptor.pb.cc
 Done processing src/descriptor.pb.h
 Done processing src/descriptor_unittest.cc
-Total errors found: 2643
+Total errors found: 2646
 
 src/descriptor.pb.cc:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/descriptor.pb.cc:9:  Found C system header after C++ system header. Should be: descriptor.pb.h, c system, c++ system, other.  [build/include_order] [4]
@@ -1626,6 +1626,8 @@ src/descriptor.pb.cc:15142:  Lines should be <= 80 characters long  [whitespace/
 src/descriptor.pb.cc:15146:  Lines should be <= 80 characters long  [whitespace/line_length] [2]
 src/descriptor.pb.cc:15150:  Lines should be <= 80 characters long  [whitespace/line_length] [2]
 src/descriptor.pb.cc:15155:  Lines should be <= 80 characters long  [whitespace/line_length] [2]
+src/descriptor.pb.cc:14981:  Add #include <utility> for swap  [build/include_what_you_use] [4]
+src/descriptor.pb.cc:15069:  Add #include <string> for string  [build/include_what_you_use] [4]
 src/descriptor.pb.cc:5:  samples/protobuf-sample/src/descriptor.pb.cc should include its header file samples/protobuf-sample/src/descriptor.pb.h  [build/include] [5]
 src/descriptor.pb.h:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/descriptor.pb.h:4:  #ifndef header guard has wrong style, please use: SAMPLES_PROTOBUF_SAMPLE_SRC_DESCRIPTOR_PB_H_  [build/header_guard] [5]
@@ -2649,4 +2651,5 @@ src/descriptor_unittest.cc:5125:  Closing ) should be moved to the previous line
 src/descriptor_unittest.cc:5929:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
 src/descriptor_unittest.cc:5968:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
 src/descriptor_unittest.cc:6486:  Redundant blank line at the end of a code block should be deleted.  [whitespace/blank_line] [3]
+src/descriptor_unittest.cc:6437:  Add #include <string> for string  [build/include_what_you_use] [4]
 
diff --git a/samples/silly-sample/includeorder_cfirst.def b/samples/silly-sample/includeorder_cfirst.def
index 05e8e66..f0e5ada 100644
--- a/samples/silly-sample/includeorder_cfirst.def
+++ b/samples/silly-sample/includeorder_cfirst.def
@@ -2,7 +2,7 @@
 1
 3
 Done processing src/sillycode.cpp
-Total errors found: 106
+Total errors found: 111
 
 src/sillycode.cpp:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/sillycode.cpp:8:  public: should be indented +1 space inside class Date  [whitespace/indent] [3]
@@ -110,4 +110,9 @@ src/sillycode.cpp:257:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:257:  At least two spaces is best between code and comments  [whitespace/comments] [2]
 src/sillycode.cpp:260:  Empty loop bodies should use {} or continue  [whitespace/empty_loop_body] [5]
 src/sillycode.cpp:260:  At least two spaces is best between code and comments  [whitespace/comments] [2]
+src/sillycode.cpp:126:  Add #include <utility> for swap  [build/include_what_you_use] [4]
+src/sillycode.cpp:168:  Add #include <memory> for unique_ptr<>  [build/include_what_you_use] [4]
+src/sillycode.cpp:224:  Add #include <limits> for numeric_limits<>  [build/include_what_you_use] [4]
+src/sillycode.cpp:237:  Add #include <string> for string  [build/include_what_you_use] [4]
+src/sillycode.cpp:244:  Add #include <iostream> for cout  [build/include_what_you_use] [4]
 
diff --git a/samples/silly-sample/sed.def b/samples/silly-sample/sed.def
index 7a0ff19..47c910d 100644
--- a/samples/silly-sample/sed.def
+++ b/samples/silly-sample/sed.def
@@ -109,4 +109,9 @@ sed -i '208s/\([^ ]\){/\1 {/' src/sillycode.cpp # Missing space before {  [white
 # src/sillycode.cpp:257:  "At least two spaces is best between code and comments"  [whitespace/comments] [2]
 # src/sillycode.cpp:260:  "Empty loop bodies should use {} or continue"  [whitespace/empty_loop_body] [5]
 # src/sillycode.cpp:260:  "At least two spaces is best between code and comments"  [whitespace/comments] [2]
+# src/sillycode.cpp:126:  "Add #include <utility> for swap"  [build/include_what_you_use] [4]
+# src/sillycode.cpp:168:  "Add #include <memory> for unique_ptr<>"  [build/include_what_you_use] [4]
+# src/sillycode.cpp:224:  "Add #include <limits> for numeric_limits<>"  [build/include_what_you_use] [4]
+# src/sillycode.cpp:237:  "Add #include <string> for string"  [build/include_what_you_use] [4]
+# src/sillycode.cpp:244:  "Add #include <iostream> for cout"  [build/include_what_you_use] [4]
 
diff --git a/samples/silly-sample/simple.def b/samples/silly-sample/simple.def
index 5b11478..0e4b5a1 100644
--- a/samples/silly-sample/simple.def
+++ b/samples/silly-sample/simple.def
@@ -2,7 +2,7 @@ src/*.cpp
 1
 3
 Done processing src/sillycode.cpp
-Total errors found: 107
+Total errors found: 112
 
 src/sillycode.cpp:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/sillycode.cpp:3:  Found C system header after C++ system header. Should be: sillycode.h, c system, c++ system, other.  [build/include_order] [4]
@@ -111,4 +111,9 @@ src/sillycode.cpp:257:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:257:  At least two spaces is best between code and comments  [whitespace/comments] [2]
 src/sillycode.cpp:260:  Empty loop bodies should use {} or continue  [whitespace/empty_loop_body] [5]
 src/sillycode.cpp:260:  At least two spaces is best between code and comments  [whitespace/comments] [2]
+src/sillycode.cpp:126:  Add #include <utility> for swap  [build/include_what_you_use] [4]
+src/sillycode.cpp:168:  Add #include <memory> for unique_ptr<>  [build/include_what_you_use] [4]
+src/sillycode.cpp:224:  Add #include <limits> for numeric_limits<>  [build/include_what_you_use] [4]
+src/sillycode.cpp:237:  Add #include <string> for string  [build/include_what_you_use] [4]
+src/sillycode.cpp:244:  Add #include <iostream> for cout  [build/include_what_you_use] [4]
 
diff --git a/samples/vlc-sample/simple.def b/samples/vlc-sample/simple.def
index 174819e..19c9563 100644
--- a/samples/vlc-sample/simple.def
+++ b/samples/vlc-sample/simple.def
@@ -4,7 +4,7 @@ src/*
 Done processing src/libvlc.c
 Done processing src/libvlc.h
 Done processing src/missing.c
-Total errors found: 601
+Total errors found: 602
 
 src/libvlc.c:41:  Found C system header after other header. Should be: libvlc.h, c system, c++ system, other.  [build/include_order] [4]
 src/libvlc.c:47:  Found C system header after other header. Should be: libvlc.h, c system, c++ system, other.  [build/include_order] [4]
@@ -367,6 +367,7 @@ src/libvlc.c:627:  Missing space before ( in if(  [whitespace/parens] [5]
 src/libvlc.c:629:  Extra space after ( in function call  [whitespace/parens] [4]
 src/libvlc.c:629:  Extra space before )  [whitespace/parens] [2]
 src/libvlc.c:640:  { should almost always be at the end of the previous line  [whitespace/braces] [4]
+src/libvlc.c:223:  Add #include <cstdio> for fclose  [build/include_what_you_use] [4]
 src/libvlc.h:0:  No #ifndef header guard found, suggested CPP variable is: SAMPLES_VLC_SAMPLE_SRC_LIBVLC_H_  [build/header_guard] [5]
 src/libvlc.h:34:  Extra space before ( in function call  [whitespace/parens] [4]
 src/libvlc.h:35:  Extra space before ( in function call  [whitespace/parens] [4]
diff --git a/tox.ini b/tox.ini
index ba060e4..59f5b00 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,24 +1,24 @@
 # also see gitlab ci.yml
 [tox]
-envlist = python3.7, python3.8, python3.9, pypy3
-
+envlist = py39, py310, py312, pypy3
 
 [gh-actions]
 python =
-    3.7: python3.7
-    3.8: python3.8
-    3.9: python3.9
-    pypy-3.9: pypy3
+    3.9: py39
+    3.10: py310
+    3.12: py312
+    pypy3.10: pypy3
 
 [testenv]
 deps =
-  python3.9: flake8>=4.0.1
-  python3.9: radon>=2.4.0
-  python3.9: pylint>=2.11.0
-  python3.9: flake8-polyfill
-  pypy3: pytest<7.2.0
+  flake8>=4.0.1
+  radon>=2.4.0
+  pylint>=2.11.0
+  flake8-polyfill
+  pytest
+  setuptools==58.2.0
 
 commands =
   {envpython} setup.py test
-  python3.9: {envpython} setup.py lint
-  python3.9: {envpython} -m flake8
+  {envpython} setup.py lint
+  {envpython} -m flake8


Test patch:
diff --git a/cpplint_clitest.py b/cpplint_clitest.py
index 500e47c..e6c88ab 100755
--- a/cpplint_clitest.py
+++ b/cpplint_clitest.py
@@ -57,6 +57,13 @@ def RunShellCommand(cmd, cwd='.'):
                             stdout=stdout_target,
                             stderr=stderr_target)
     out, err = proc.communicate()
+
+    # Make output system-agnostic, aka support Windows
+    if os.sep == '\\':
+        out, err = out.replace(b'\\', b'/'), err.replace(b'\\', b'/')
+    if os.linesep == '\r\n':
+        out, err = out.replace(b'\r\n', b'\n'), err.replace(b'\r\n', b'\n')
+
     # print(err) # to get the output at time of test
     return (proc.returncode, out, err)
 
@@ -170,7 +177,7 @@ class NoRepoSignatureTests(TemporaryFolderClassSetup, unittest.TestCase):
         self.checkAllInFolder('./samples/cfg-file', 1)
 
     def testBoostSample(self):
-        self.checkAllInFolder('./samples/boost-sample', 4)
+        self.checkAllInFolder('./samples/boost-sample', 5)
 
     def testProtobufSample(self):
         self.checkAllInFolder('./samples/protobuf-sample', 1)
diff --git a/cpplint_unittest.py b/cpplint_unittest.py
index e0ad860..4bab1c9 100755
--- a/cpplint_unittest.py
+++ b/cpplint_unittest.py
@@ -46,30 +46,6 @@ import pytest
 
 import cpplint
 
-try:
-  xrange          # Python 2
-except NameError:
-  #  -- pylint: disable=redefined-builtin
-  xrange = range  # Python 3
-
-try:
-  unicode
-except NameError:
-  #  -- pylint: disable=redefined-builtin
-  basestring = unicode = str
-
-try:
-  long(2)
-except NameError:
-  #  -- pylint: disable=redefined-builtin
-  long = int
-
-def unicode_escape_decode(x):
-  if sys.version_info < (3,):
-    return codecs.unicode_escape_decode(x)[0]
-  else:
-    return x
-
 def codecs_latin_encode(x):
   if sys.version_info < (3,):
     return x
@@ -152,13 +128,15 @@ class CpplintTestBase(unittest.TestCase):
   def setUp(self):
     # Allow subclasses to cheat os.path.abspath called in FileInfo class.
     self.os_path_abspath_orig = os.path.abspath
+    self.assertEqual = self.assertEqual
+    self.assertTrue = self.assertTrue
 
   def tearDown(self):
     os.path.abspath = self.os_path_abspath_orig
 
   # Perform lint on single line of input and return the error message.
   def PerformSingleLineLint(self, code):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     lines = code.split('\n')
     cpplint.RemoveMultiLineComments('foo.h', lines, error_collector)
     clean_lines = cpplint.CleansedLines(lines)
@@ -176,12 +154,12 @@ class CpplintTestBase(unittest.TestCase):
 
   # Perform lint over multiple lines and return the error message.
   def PerformMultiLineLint(self, code):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     lines = code.split('\n')
     cpplint.RemoveMultiLineComments('foo.h', lines, error_collector)
     lines = cpplint.CleansedLines(lines)
     nesting_state = cpplint.NestingState()
-    for i in xrange(lines.NumLines()):
+    for i in range(lines.NumLines()):
       nesting_state.Update('foo.h', lines, i, error_collector)
       cpplint.CheckStyle('foo.h', lines, i, 'h', nesting_state,
                          error_collector)
@@ -193,14 +171,14 @@ class CpplintTestBase(unittest.TestCase):
   # Similar to PerformMultiLineLint, but calls CheckLanguage instead of
   # CheckForNonStandardConstructs
   def PerformLanguageRulesCheck(self, file_name, code):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     include_state = cpplint._IncludeState()
     nesting_state = cpplint.NestingState()
     lines = code.split('\n')
     cpplint.RemoveMultiLineComments(file_name, lines, error_collector)
     lines = cpplint.CleansedLines(lines)
     ext = file_name[file_name.rfind('.') + 1:]
-    for i in xrange(lines.NumLines()):
+    for i in range(lines.NumLines()):
       cpplint.CheckLanguage(file_name, lines, i, ext, include_state,
                             nesting_state, error_collector)
     return error_collector.Results()
@@ -221,25 +199,25 @@ class CpplintTestBase(unittest.TestCase):
       The accumulated errors.
     """
     file_name = 'foo.cc'
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     function_state = cpplint._FunctionState()
     lines = code.split('\n')
     cpplint.RemoveMultiLineComments(file_name, lines, error_collector)
     lines = cpplint.CleansedLines(lines)
-    for i in xrange(lines.NumLines()):
+    for i in range(lines.NumLines()):
       cpplint.CheckForFunctionLengths(file_name, lines, i,
                                       function_state, error_collector)
     return error_collector.Results()
 
   def PerformIncludeWhatYouUse(self, code, filename='foo.h', io=codecs):
     # First, build up the include state.
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     include_state = cpplint._IncludeState()
     nesting_state = cpplint.NestingState()
     lines = code.split('\n')
     cpplint.RemoveMultiLineComments(filename, lines, error_collector)
     lines = cpplint.CleansedLines(lines)
-    for i in xrange(lines.NumLines()):
+    for i in range(lines.NumLines()):
       cpplint.CheckLanguage(filename, lines, i, '.h', include_state,
                             nesting_state, error_collector)
     # We could clear the error_collector here, but this should
@@ -253,10 +231,10 @@ class CpplintTestBase(unittest.TestCase):
 
   # Perform lint and compare the error message with "expected_message".
   def TestLint(self, code, expected_message):
-    self.assertEquals(expected_message, self.PerformSingleLineLint(code))
+    self.assertEqual(expected_message, self.PerformSingleLineLint(code))
 
   def TestMultiLineLint(self, code, expected_message):
-    self.assertEquals(expected_message, self.PerformMultiLineLint(code))
+    self.assertEqual(expected_message, self.PerformMultiLineLint(code))
 
   def TestMultiLineLintRE(self, code, expected_message_re):
     message = self.PerformMultiLineLint(code)
@@ -265,11 +243,11 @@ class CpplintTestBase(unittest.TestCase):
                 expected_message_re + '"')
 
   def TestLanguageRulesCheck(self, file_name, code, expected_message):
-    self.assertEquals(expected_message,
+    self.assertEqual(expected_message,
                       self.PerformLanguageRulesCheck(file_name, code))
 
   def TestIncludeWhatYouUse(self, code, expected_message):
-    self.assertEquals(expected_message,
+    self.assertEqual(expected_message,
                       self.PerformIncludeWhatYouUse(code))
 
   def TestBlankLinesCheck(self, lines, start_errors, end_errors):
@@ -277,14 +255,14 @@ class CpplintTestBase(unittest.TestCase):
       self.doTestBlankLinesCheck(lines, start_errors, end_errors, extension)
 
   def doTestBlankLinesCheck(self, lines, start_errors, end_errors, extension):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.' + extension, extension, lines, error_collector)
-    self.assertEquals(
+    self.assertEqual(
         start_errors,
         error_collector.Results().count(
             'Redundant blank line at the start of a code block '
             'should be deleted.  [whitespace/blank_line] [2]'))
-    self.assertEquals(
+    self.assertEqual(
         end_errors,
         error_collector.Results().count(
             'Redundant blank line at the end of a code block '
@@ -294,11 +272,11 @@ class CpplintTestBase(unittest.TestCase):
 class CpplintTest(CpplintTestBase):
 
   def GetNamespaceResults(self, lines):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.RemoveMultiLineComments('foo.h', lines, error_collector)
     lines = cpplint.CleansedLines(lines)
     nesting_state = cpplint.NestingState()
-    for i in xrange(lines.NumLines()):
+    for i in range(lines.NumLines()):
       nesting_state.Update('foo.h', lines, i, error_collector)
       cpplint.CheckForNamespaceIndentation('foo.h', nesting_state,
                                            lines, i, error_collector)
@@ -311,7 +289,7 @@ class CpplintTest(CpplintTestBase):
              '}  // namespace Test']
 
     results = self.GetNamespaceResults(lines)
-    self.assertEquals(results, 'Do not indent within a namespace '
+    self.assertEqual(results, 'Do not indent within a namespace '
                       ' [runtime/indentation_namespace] [4]')
 
   def testNameSpaceIndentationForClass(self):
@@ -322,7 +300,7 @@ class CpplintTest(CpplintTestBase):
              '}  // namespace Test']
 
     results = self.GetNamespaceResults(lines)
-    self.assertEquals(results, 'Do not indent within a namespace '
+    self.assertEqual(results, 'Do not indent within a namespace '
                       ' [runtime/indentation_namespace] [4]')
 
   def testNameSpaceIndentationNoError(self):
@@ -331,7 +309,7 @@ class CpplintTest(CpplintTestBase):
              '}  // namespace Test']
 
     results = self.GetNamespaceResults(lines)
-    self.assertEquals(results, '')
+    self.assertEqual(results, '')
 
   def testWhitespaceBeforeNamespace(self):
     lines = ['  namespace Test {',
@@ -339,7 +317,7 @@ class CpplintTest(CpplintTestBase):
              '  }  // namespace Test']
 
     results = self.GetNamespaceResults(lines)
-    self.assertEquals(results, '')
+    self.assertEqual(results, '')
 
   def testFalsePositivesNoError(self):
     lines = ['namespace Test {',
@@ -350,34 +328,34 @@ class CpplintTest(CpplintTestBase):
              '}  // namespace Test']
 
     results = self.GetNamespaceResults(lines)
-    self.assertEquals(results, '')
+    self.assertEqual(results, '')
 
   # Test get line width.
   def testGetLineWidth(self):
-    self.assertEquals(0, cpplint.GetLineWidth(''))
-    self.assertEquals(10, cpplint.GetLineWidth(unicode('x') * 10))
-    self.assertEquals(16, cpplint.GetLineWidth(unicode_escape_decode('\u90fd|\u9053|\u5e9c|\u770c|\u652f\u5e81')))
-    self.assertEquals(16, cpplint.GetLineWidth(u'都|道|府|県|支庁'))
-    self.assertEquals(5 + 13 + 9, cpplint.GetLineWidth(
+    self.assertEqual(0, cpplint.GetLineWidth(''))
+    self.assertEqual(10, cpplint.GetLineWidth(str('x') * 10))
+    self.assertEqual(16, cpplint.GetLineWidth('\u90fd|\u9053|\u5e9c|\u770c|\u652f\u5e81'))
+    self.assertEqual(16, cpplint.GetLineWidth(u'都|道|府|県|支庁'))
+    self.assertEqual(5 + 13 + 9, cpplint.GetLineWidth(
         u'd𝐱/dt' + u'f : t ⨯ 𝐱 → ℝ' + u't ⨯ 𝐱 → ℝ'))
 
   def testGetTextInside(self):
-    self.assertEquals('', cpplint._GetTextInside('fun()', r'fun\('))
-    self.assertEquals('x, y', cpplint._GetTextInside('f(x, y)', r'f\('))
-    self.assertEquals('a(), b(c())', cpplint._GetTextInside(
+    self.assertEqual('', cpplint._GetTextInside('fun()', r'fun\('))
+    self.assertEqual('x, y', cpplint._GetTextInside('f(x, y)', r'f\('))
+    self.assertEqual('a(), b(c())', cpplint._GetTextInside(
         'printf(a(), b(c()))', r'printf\('))
-    self.assertEquals('x, y{}', cpplint._GetTextInside('f[x, y{}]', r'f\['))
-    self.assertEquals(None, cpplint._GetTextInside('f[a, b(}]', r'f\['))
-    self.assertEquals(None, cpplint._GetTextInside('f[x, y]', r'f\('))
-    self.assertEquals('y, h(z, (a + b))', cpplint._GetTextInside(
+    self.assertEqual('x, y{}', cpplint._GetTextInside('f[x, y{}]', r'f\['))
+    self.assertEqual(None, cpplint._GetTextInside('f[a, b(}]', r'f\['))
+    self.assertEqual(None, cpplint._GetTextInside('f[x, y]', r'f\('))
+    self.assertEqual('y, h(z, (a + b))', cpplint._GetTextInside(
         'f(x, g(y, h(z, (a + b))))', r'g\('))
-    self.assertEquals('f(f(x))', cpplint._GetTextInside('f(f(f(x)))', r'f\('))
+    self.assertEqual('f(f(x))', cpplint._GetTextInside('f(f(f(x)))', r'f\('))
     # Supports multiple lines.
-    self.assertEquals('\n  return loop(x);\n',
+    self.assertEqual('\n  return loop(x);\n',
                       cpplint._GetTextInside(
                           'int loop(int x) {\n  return loop(x);\n}\n', r'\{'))
     # '^' matches the beginning of each line.
-    self.assertEquals('x, y',
+    self.assertEqual('x, y',
                       cpplint._GetTextInside(
                           '#include "inl.h"  // skip #define\n'
                           '#define A2(x, y) a_inl_(x, y, __LINE__)\n'
@@ -385,23 +363,23 @@ class CpplintTest(CpplintTestBase):
                           r'^\s*#define\s*\w+\('))
 
   def testFindNextMultiLineCommentStart(self):
-    self.assertEquals(1, cpplint.FindNextMultiLineCommentStart([''], 0))
+    self.assertEqual(1, cpplint.FindNextMultiLineCommentStart([''], 0))
 
     lines = ['a', 'b', '/* c']
-    self.assertEquals(2, cpplint.FindNextMultiLineCommentStart(lines, 0))
+    self.assertEqual(2, cpplint.FindNextMultiLineCommentStart(lines, 0))
 
     lines = ['char a[] = "/*";']  # not recognized as comment.
-    self.assertEquals(1, cpplint.FindNextMultiLineCommentStart(lines, 0))
+    self.assertEqual(1, cpplint.FindNextMultiLineCommentStart(lines, 0))
 
   def testFindNextMultiLineCommentEnd(self):
-    self.assertEquals(1, cpplint.FindNextMultiLineCommentEnd([''], 0))
+    self.assertEqual(1, cpplint.FindNextMultiLineCommentEnd([''], 0))
     lines = ['a', 'b', ' c */']
-    self.assertEquals(2, cpplint.FindNextMultiLineCommentEnd(lines, 0))
+    self.assertEqual(2, cpplint.FindNextMultiLineCommentEnd(lines, 0))
 
   def testRemoveMultiLineCommentsFromRange(self):
     lines = ['a', '  /* comment ', ' * still comment', ' comment */   ', 'b']
     cpplint.RemoveMultiLineCommentsFromRange(lines, 1, 4)
-    self.assertEquals(['a', '/**/', '/**/', '/**/', 'b'], lines)
+    self.assertEqual(['a', '/**/', '/**/', '/**/', 'b'], lines)
 
   def testSpacesAtEndOfLine(self):
     self.TestLint(
@@ -493,6 +471,11 @@ class CpplintTest(CpplintTestBase):
         'long a = (int64) 65;  // NOLINT(runtime/int)',
         'Using C-style cast.  Use static_cast<int64>(...) instead'
         '  [readability/casting] [4]')
+    # Two categories of errors suppressed:
+    self.TestLint(
+        'long a = (int64) 65;  // NOLINT(runtime/int,readability/casting)',
+        '')
+
     # All categories suppressed: (two aliases)
     self.TestLint('long a = (int64) 65;  // NOLINT', '')
     self.TestLint('long a = (int64) 65;  // NOLINT(*)', '')
@@ -509,16 +492,25 @@ class CpplintTest(CpplintTestBase):
         'Use int16/int64/etc, rather than the C type long'
         '  [runtime/int] [4]')
     # NOLINTNEXTLINE silences warning for the next line instead of current line
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('test.cc', 'cc',
                             ['// Copyright 2014 Your Company.',
                              '// NOLINTNEXTLINE(whitespace/line_length)',
                              '//  ./command' + (' -verbose' * 80),
                              ''],
                             error_collector)
-    self.assertEquals('', error_collector.Results())
+    self.assertEqual('', error_collector.Results())
+    # NOLINTNEXTLINE multiple categories silences warning for the next line instead of current line
+    error_collector = ErrorCollector(self.assertTrue)
+    cpplint.ProcessFileData('test.cc', 'cc',
+                            ['// Copyright 2014 Your Company.',
+                             '// NOLINTNEXTLINE(runtime/int,readability/casting)',
+                             'long a = (int64) 65;',
+                             ''],
+                            error_collector)
+    self.assertEqual('', error_collector.Results())
     # LINT_C_FILE silences cast warnings for entire file.
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('test.h', 'h',
                             ['// Copyright 2014 Your Company.',
                              '// NOLINT(build/header_guard)',
@@ -526,7 +518,7 @@ class CpplintTest(CpplintTestBase):
                              '//  LINT_C_FILE',
                              ''],
                             error_collector)
-    self.assertEquals('', error_collector.Results())
+    self.assertEqual('', error_collector.Results())
     # Vim modes silence cast warnings for entire file.
     for modeline in ['vi:filetype=c',
                      'vi:sw=8 filetype=c',
@@ -552,7 +544,7 @@ class CpplintTest(CpplintTestBase):
                      'vim: se filetype=c :',
                      'vim: se sw=8 filetype=c :',
                      'vim: se sw=8 filetype=c ts=8 :']:
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData('test.h', 'h',
                               ['// Copyright 2014 Your Company.',
                                '// NOLINT(build/header_guard)',
@@ -562,9 +554,9 @@ class CpplintTest(CpplintTestBase):
                                '*/',
                                ''],
                               error_collector)
-      self.assertEquals('', error_collector.Results())
+      self.assertEqual('', error_collector.Results())
     # LINT_KERNEL_FILE silences whitespace/tab warnings for entire file.
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('test.h', 'h',
                             ['// Copyright 2014 Your Company.',
                              '// NOLINT(build/header_guard)',
@@ -574,11 +566,12 @@ class CpplintTest(CpplintTestBase):
                              '//  LINT_KERNEL_FILE',
                              ''],
                             error_collector)
-    self.assertEquals('', error_collector.Results())
+    self.assertEqual('', error_collector.Results())
     # NOLINT, NOLINTNEXTLINE silences the readability/braces warning for "};".
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('test.cc', 'cc',
                             ['// Copyright 2014 Your Company.',
+                             '#include <iostream>',
                              'for (int i = 0; i != 100; ++i) {',
                              '  std::cout << i << std::endl;',
                              '};  // NOLINT',
@@ -589,7 +582,7 @@ class CpplintTest(CpplintTestBase):
                              '//  LINT_KERNEL_FILE',
                              ''],
                             error_collector)
-    self.assertEquals('', error_collector.Results())
+    self.assertEqual('', error_collector.Results())
 
   # Test Variable Declarations.
   def testVariableDeclarations(self):
@@ -837,7 +830,7 @@ class CpplintTest(CpplintTestBase):
     self.TestLint('std::function< int(bool) >', '')
     self.TestLint('mfunction<int(bool)>', '')
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(
         'test.cc', 'cc',
         ['// Copyright 2014 Your Company. All Rights Reserved.',
@@ -845,7 +838,7 @@ class CpplintTest(CpplintTestBase):
          '    bool(int)> F;',
          ''],
         error_collector)
-    self.assertEquals('', error_collector.Results())
+    self.assertEqual('', error_collector.Results())
 
     # Return types for function pointers
     self.TestLint('typedef bool(FunctionPointer)();', '')
@@ -876,7 +869,7 @@ class CpplintTest(CpplintTestBase):
         'MOCK_CONST_METHOD1(method, SomeType(int));',
         '')
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('mock.cc', 'cc',
                             ['MOCK_METHOD1(method1,',
                              '             bool(int));',
@@ -889,13 +882,13 @@ class CpplintTest(CpplintTestBase):
                              'MOCK_METHOD1(method4, int(bool));',
                              'const int kConstant = int(42);'],  # true positive
                             error_collector)
-    self.assertEquals(
+    self.assertEqual(
         0,
         error_collector.Results().count(
             ('Using deprecated casting style.  '
              'Use static_cast<bool>(...) instead  '
              '[readability/casting] [4]')))
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.Results().count(
             ('Using deprecated casting style.  '
@@ -940,13 +933,11 @@ class CpplintTest(CpplintTestBase):
 
   def testIncludeWhatYouUseNoImplementationFiles(self):
     code = 'std::vector<int> foo;'
-    for extension in ['h', 'hpp', 'hxx', 'h++', 'cuh']:
+    for extension in ['h', 'hpp', 'hxx', 'h++', 'cuh',
+                      'c', 'cc', 'cpp', 'cxx', 'c++', 'cu']:
       self.assertEquals('Add #include <vector> for vector<>'
                        '  [build/include_what_you_use] [4]',
                        self.PerformIncludeWhatYouUse(code, 'foo.' + extension))
-    for extension in ['c', 'cc', 'cpp', 'cxx', 'c++', 'cu']:
-      self.assertEquals('',
-                       self.PerformIncludeWhatYouUse(code, 'foo.' + extension))
 
   def testIncludeWhatYouUse(self):
     self.TestIncludeWhatYouUse(
@@ -1033,6 +1024,12 @@ class CpplintTest(CpplintTestBase):
            bool foobar = min<int>(0,1);
         """,
         'Add #include <algorithm> for min  [build/include_what_you_use] [4]')
+    self.TestIncludeWhatYouUse(
+        'cout << "hello world" << endl;',
+        'Add #include <iostream> for cout  [build/include_what_you_use] [4]')
+    self.TestIncludeWhatYouUse(
+        'printf("hello world");',
+        'Add #include <cstdio> for printf  [build/include_what_you_use] [4]')
     self.TestIncludeWhatYouUse(
         'void a(const string &foobar);',
         'Add #include <string> for string  [build/include_what_you_use] [4]')
@@ -1160,87 +1157,43 @@ class CpplintTest(CpplintTestBase):
         """,
         '')
 
-    # Test the UpdateIncludeState code path.
-    mock_header_contents = ['#include "blah/foo.h"', '#include "blah/bar.h"']
-    message = self.PerformIncludeWhatYouUse(
-        '#include "blah/a.h"',
-        filename='blah/a.cc',
-        io=MockIo(mock_header_contents))
-    self.assertEquals(message, '')
-
-    mock_header_contents = ['#include <set>']
-    message = self.PerformIncludeWhatYouUse(
-        """#include "blah/a.h"
-           std::set<int> foo;""",
-        filename='blah/a.cc',
-        io=MockIo(mock_header_contents))
-    self.assertEquals(message, '')
-
-    # Make sure we can find the correct header file if the cc file seems to be
-    # a temporary file generated by Emacs's flymake.
-    mock_header_contents = ['']
-    message = self.PerformIncludeWhatYouUse(
-        """#include "blah/a.h"
-           std::set<int> foo;""",
-        filename='blah/a_flymake.cc',
-        io=MockIo(mock_header_contents))
-    self.assertEquals(message, 'Add #include <set> for set<>  '
-                      '[build/include_what_you_use] [4]')
-
-    # If there's just a cc and the header can't be found then it's ok.
-    message = self.PerformIncludeWhatYouUse(
-        """#include "blah/a.h"
-           std::set<int> foo;""",
-        filename='blah/a.cc')
-    self.assertEquals(message, '')
-
-    # Make sure we find the headers with relative paths.
-    mock_header_contents = ['']
-    message = self.PerformIncludeWhatYouUse(
-        """#include "%s/a.h"
-           std::set<int> foo;""" % os.path.basename(os.getcwd()),
-        filename='a.cc',
-        io=MockIo(mock_header_contents))
-    self.assertEquals(message, 'Add #include <set> for set<>  '
-                      '[build/include_what_you_use] [4]')
-
   def testFilesBelongToSameModule(self):
     f = cpplint.FilesBelongToSameModule
-    self.assertEquals((True, ''), f('a.cc', 'a.h'))
-    self.assertEquals((True, ''), f('base/google.cc', 'base/google.h'))
-    self.assertEquals((True, ''), f('base/google_test.c', 'base/google.h'))
-    self.assertEquals((True, ''), f('base/google_test.cc', 'base/google.h'))
-    self.assertEquals((True, ''), f('base/google_test.cc', 'base/google.hpp'))
-    self.assertEquals((True, ''), f('base/google_test.cxx', 'base/google.hxx'))
-    self.assertEquals((True, ''), f('base/google_test.cpp', 'base/google.hpp'))
-    self.assertEquals((True, ''), f('base/google_test.c++', 'base/google.h++'))
-    self.assertEquals((True, ''), f('base/google_test.cu', 'base/google.cuh'))
-    self.assertEquals((True, ''),
+    self.assertEqual((True, ''), f('a.cc', 'a.h'))
+    self.assertEqual((True, ''), f('base/google.cc', 'base/google.h'))
+    self.assertEqual((True, ''), f('base/google_test.c', 'base/google.h'))
+    self.assertEqual((True, ''), f('base/google_test.cc', 'base/google.h'))
+    self.assertEqual((True, ''), f('base/google_test.cc', 'base/google.hpp'))
+    self.assertEqual((True, ''), f('base/google_test.cxx', 'base/google.hxx'))
+    self.assertEqual((True, ''), f('base/google_test.cpp', 'base/google.hpp'))
+    self.assertEqual((True, ''), f('base/google_test.c++', 'base/google.h++'))
+    self.assertEqual((True, ''), f('base/google_test.cu', 'base/google.cuh'))
+    self.assertEqual((True, ''),
                       f('base/google_unittest.cc', 'base/google.h'))
-    self.assertEquals((True, ''),
+    self.assertEqual((True, ''),
                       f('base/internal/google_unittest.cc',
                         'base/public/google.h'))
-    self.assertEquals((True, 'xxx/yyy/'),
+    self.assertEqual((True, 'xxx/yyy/'),
                       f('xxx/yyy/base/internal/google_unittest.cc',
                         'base/public/google.h'))
-    self.assertEquals((True, 'xxx/yyy/'),
+    self.assertEqual((True, 'xxx/yyy/'),
                       f('xxx/yyy/base/google_unittest.cc',
                         'base/public/google.h'))
-    self.assertEquals((True, ''),
+    self.assertEqual((True, ''),
                       f('base/google_unittest.cc', 'base/google-inl.h'))
-    self.assertEquals((True, '/home/build/google3/'),
+    self.assertEqual((True, '/home/build/google3/'),
                       f('/home/build/google3/base/google.cc', 'base/google.h'))
 
-    self.assertEquals((False, ''),
+    self.assertEqual((False, ''),
                       f('/home/build/google3/base/google.cc', 'basu/google.h'))
-    self.assertEquals((False, ''), f('a.cc', 'b.h'))
+    self.assertEqual((False, ''), f('a.cc', 'b.h'))
 
   def testCleanseLine(self):
-    self.assertEquals('int foo = 0;',
+    self.assertEqual('int foo = 0;',
                       cpplint.CleanseComments('int foo = 0;  // danger!'))
-    self.assertEquals('int o = 0;',
+    self.assertEqual('int o = 0;',
                       cpplint.CleanseComments('int /* foo */ o = 0;'))
-    self.assertEquals('foo(int a, int b);',
+    self.assertEqual('foo(int a, int b);',
                       cpplint.CleanseComments('foo(int a /* abc */, int b);'))
     self.assertEqual('f(a, b);',
                      cpplint.CleanseComments('f(a, /* name */ b);'))
@@ -1373,12 +1326,12 @@ class CpplintTest(CpplintTestBase):
     for extension in ['c', 'cc', 'cpp', 'cxx', 'c++', 'cu']:
       file_path = 'mydir/foo.' + extension
 
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData(file_path, extension,
                               ['const char* str = "This is a\\',
                                ' multiline string.";'],
                               error_collector)
-      self.assertEquals(
+      self.assertEqual(
           2,  # One per line.
           error_collector.ResultList().count(multiline_string_error_message))
 
@@ -1724,48 +1677,48 @@ class CpplintTest(CpplintTestBase):
           };""",
           '')
       # Special case for variadic arguments
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData('foo.cc', 'cc',
           ['class Foo {',
           '  template<typename... Args>',
           '  explicit Foo(const int arg, Args&&... args) {}',
           '};'],
           error_collector)
-      self.assertEquals(0, error_collector.ResultList().count(
+      self.assertEqual(0, error_collector.ResultList().count(
         'Constructors that require multiple arguments should not be marked '
         'explicit.  [runtime/explicit] [0]'))
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData('foo.cc', 'cc',
           ['class Foo {',
           '  template<typename... Args>',
           '  explicit Foo(Args&&... args) {}',
           '};'],
           error_collector)
-      self.assertEquals(0, error_collector.ResultList().count(
+      self.assertEqual(0, error_collector.ResultList().count(
         'Constructors that require multiple arguments should not be marked '
         'explicit.  [runtime/explicit] [0]'))
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData('foo.cc', 'cc',
           ['class Foo {',
           '  template<typename... Args>',
           '  Foo(const int arg, Args&&... args) {}',
           '};'],
           error_collector)
-      self.assertEquals(1, error_collector.ResultList().count(
+      self.assertEqual(1, error_collector.ResultList().count(
         'Constructors callable with one argument should be marked explicit.'
         '  [runtime/explicit] [5]'))
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData('foo.cc', 'cc',
           ['class Foo {',
           '  template<typename... Args>',
           '  Foo(Args&&... args) {}',
           '};'],
           error_collector)
-      self.assertEquals(1, error_collector.ResultList().count(
+      self.assertEqual(1, error_collector.ResultList().count(
         'Constructors callable with one argument should be marked explicit.'
         '  [runtime/explicit] [5]'))
       # Anything goes inside an assembly block
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData('foo.cc', 'cc',
                               ['void Func() {',
                                '  __asm__ (',
@@ -1776,16 +1729,16 @@ class CpplintTest(CpplintTestBase):
                                '  }',
                                '}'],
                               error_collector)
-      self.assertEquals(
+      self.assertEqual(
           0,
           error_collector.ResultList().count(
               'Extra space before ( in function call  [whitespace/parens] [4]'))
-      self.assertEquals(
+      self.assertEqual(
           0,
           error_collector.ResultList().count(
               'Closing ) should be moved to the previous line  '
               '[whitespace/parens] [2]'))
-      self.assertEquals(
+      self.assertEqual(
           0,
           error_collector.ResultList().count(
               'Extra space before [  [whitespace/braces] [5]'))
@@ -1875,7 +1828,7 @@ class CpplintTest(CpplintTestBase):
       self.TestLint('virtual int F() %s;' % virt_specifier, error_message)
       self.TestLint('virtual int F() %s {' % virt_specifier, error_message)
 
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData(
           'foo.cc', 'cc',
           ['// Copyright 2014 Your Company.',
@@ -1888,7 +1841,7 @@ class CpplintTest(CpplintTestBase):
            '    LOCKS_EXCLUDED(lock) ' + virt_specifier + ';',
            ''],
           error_collector)
-      self.assertEquals(
+      self.assertEqual(
           [error_message, error_message, error_message],
           error_collector.Results())
 
@@ -1900,7 +1853,7 @@ class CpplintTest(CpplintTestBase):
     self.TestLint('int F() final override;', error_message)
     self.TestLint('int F() final override {}', error_message)
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(
         'foo.cc', 'cc',
         ['// Copyright 2014 Your Company.',
@@ -1914,7 +1867,7 @@ class CpplintTest(CpplintTestBase):
          '}',
          ''],
         error_collector)
-    self.assertEquals('', error_collector.Results())
+    self.assertEqual('', error_collector.Results())
 
     self.TestLint('void Finalize(AnnotationProto *final) override;', '')
 
@@ -2074,7 +2027,7 @@ class CpplintTest(CpplintTestBase):
     for macro_name in (
         'DISALLOW_COPY_AND_ASSIGN',
         'DISALLOW_IMPLICIT_CONSTRUCTORS'):
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData(
           'foo.cc', 'cc',
           ['// Copyright 2014 Your Company.',
@@ -2085,12 +2038,12 @@ class CpplintTest(CpplintTestBase):
            '};',
            ''],
           error_collector)
-      self.assertEquals(
+      self.assertEqual(
           ('%s should be the last thing in the class' % macro_name) +
           '  [readability/constructors] [3]',
           error_collector.Results())
 
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData(
           'foo.cc', 'cc',
           ['// Copyright 2014 Your Company.',
@@ -2104,12 +2057,12 @@ class CpplintTest(CpplintTestBase):
            '};',
            ''],
           error_collector)
-      self.assertEquals(
+      self.assertEqual(
           ('%s should be the last thing in the class' % macro_name) +
           '  [readability/constructors] [3]',
           error_collector.Results())
 
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData(
           'foo.cc', 'cc',
           ['// Copyright 2014 Your Company.',
@@ -2141,7 +2094,7 @@ class CpplintTest(CpplintTestBase):
            '}',
            ''],
           error_collector)
-      self.assertEquals('', error_collector.Results())
+      self.assertEqual('', error_collector.Results())
 
   # Brace usage
   def testBraces(self):
@@ -2442,7 +2395,7 @@ class CpplintTest(CpplintTestBase):
 
     # Don't warn on out-of-line method definitions.
     self.TestLint('void NS::Func(X& x) {', '')
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(
         'foo.cc', 'cc',
         ['// Copyright 2014 Your Company. All Rights Reserved.',
@@ -2450,16 +2403,18 @@ class CpplintTest(CpplintTestBase):
          'void f(int& q) {}',
          ''],
         error_collector)
-    self.assertEquals(
+    self.assertEqual(
         operand_error_message % 'int& q',
         error_collector.Results())
 
     # Other potential false positives.  These need full parser
     # state to reproduce as opposed to just TestLint.
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(
         'foo.cc', 'cc',
         ['// Copyright 2014 Your Company. All Rights Reserved.',
+         '#include <string>',
+         '#include <utility>',
          'void swap(int &x,',
          '          int &y) {',
          '}',
@@ -2496,10 +2451,10 @@ class CpplintTest(CpplintTestBase):
          '      initializer2_(a6 & b6) {}',
          ''],
         error_collector)
-    self.assertEquals('', error_collector.Results())
+    self.assertEqual('', error_collector.Results())
 
     # Multi-line references
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(
         'foo.cc', 'cc',
         ['// Copyright 2014 Your Company. All Rights Reserved.',
@@ -2518,14 +2473,14 @@ class CpplintTest(CpplintTestBase):
          '}',
          ''],
         error_collector)
-    self.assertEquals(
+    self.assertEqual(
         [operand_error_message % 'Outer::Inner& nonconst_x',
          operand_error_message % 'Outer::Inner& nonconst_y',
          operand_error_message % 'Outer<int>::Inner& nonconst_z'],
         error_collector.Results())
 
     # A peculiar false positive due to bad template argument parsing
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(
         'foo.cc', 'cc',
         ['// Copyright 2014 Your Company. All Rights Reserved.',
@@ -2538,14 +2493,14 @@ class CpplintTest(CpplintTestBase):
          '}',
          ''],
         error_collector.Results())
-    self.assertEquals('', error_collector.Results())
+    self.assertEqual('', error_collector.Results())
 
   def testBraceAtBeginOfLine(self):
     self.TestLint('{',
                   '{ should almost always be at the end of the previous line'
                   '  [whitespace/braces] [4]')
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['int function()',
                              '{',  # warning here
@@ -2567,7 +2522,7 @@ class CpplintTest(CpplintTestBase):
                              '}',
                              '#endif'],
                             error_collector)
-    self.assertEquals(1, error_collector.Results().count(
+    self.assertEqual(1, error_collector.Results().count(
         '{ should almost always be at the end of the previous line'
         '  [whitespace/braces] [4]'))
 
@@ -2659,6 +2614,39 @@ class CpplintTest(CpplintTestBase):
     self.TestLint('sizeof foo', '')
     self.TestLint('sizeof (foo)', '')
 
+  def testReplaceAlternateTokens(self):
+    assert cpplint.ReplaceAlternateTokens('tor or orc') == 'tor || orc'
+    assert cpplint.ReplaceAlternateTokens('orc or tor') == 'orc || tor'
+    assert cpplint.ReplaceAlternateTokens('tor or (orc)') == 'tor || (orc)'
+    assert cpplint.ReplaceAlternateTokens('tor or(orc)') == 'tor ||(orc)'
+    assert cpplint.ReplaceAlternateTokens('sand and(android)') == \
+                                          'sand &&(android)'
+    assert cpplint.ReplaceAlternateTokens('(sand) and (android)') == \
+                                          '(sand) && (android)'
+    assert cpplint.ReplaceAlternateTokens(' not note') == ' !note'
+    assert cpplint.ReplaceAlternateTokens(')not note') == ')!note'
+    assert cpplint.ReplaceAlternateTokens('(not note') == '(!note'
+    assert cpplint.ReplaceAlternateTokens(' not(note)') == ' !(note)'
+    assert cpplint.ReplaceAlternateTokens(' not (splinot)') == ' !(splinot)'
+    assert cpplint.ReplaceAlternateTokens('tor and orc or android') == \
+                                          'tor && orc || android'
+    assert cpplint.ReplaceAlternateTokens('tor or orc and ands not note') == \
+                                          'tor || orc && ands !note'
+
+  def testSpacingAfterAlternateToken(self):
+    try:
+      cpplint._cpplint_state.AddFilters('-readability/alt_tokens')
+      self.TestLint('if (foo or (bar) or foobar) {', '')
+      self.TestLint('if (foo or (bar)) {', '')
+      self.TestLint('if ((foo) or (bar)) {', '')
+      self.TestLint('if (not foo) {', '')
+      self.TestLint('if (not (foo)) {', '')
+      self.TestLint('if (not(foo)) {', '')
+      self.TestLint('if ((foo)or(bar)) {', 'Missing spaces around ||'
+                    '  [whitespace/operators] [3]')
+    finally:
+      cpplint._cpplint_state.SetFilters('')
+
   def testSpacingBeforeBraces(self):
     self.TestLint('if (foo){', 'Missing space before {'
                   '  [whitespace/braces] [5]')
@@ -3056,9 +3044,10 @@ class CpplintTest(CpplintTestBase):
                   '}\n', '')
 
     # Check multiline cases.
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['// Copyright 2014 Your Company.',
+                             '#include <string>',
                              'string Class',
                              '::MemberFunction1();',
                              'string Class::',
@@ -3079,7 +3068,7 @@ class CpplintTest(CpplintTestBase):
                              'static_member_variable5;',
                              ''],
                             error_collector)
-    self.assertEquals(error_collector.Results(),
+    self.assertEqual(error_collector.Results(),
                       [error_msg % 'const char Class::static_member_variable1',
                        error_msg % 'const char Class::static_member_variable2',
                        error_msg % 'const char Class::static_member_variable3',
@@ -3207,10 +3196,10 @@ class CpplintTest(CpplintTestBase):
   # 1' line was also causing the issue.
   def testLinePrecededByEmptyOrCommentLines(self):
     def DoTest(self, lines):
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData('foo.cc', 'cc', lines, error_collector)
       # The warning appears only once.
-      self.assertEquals(
+      self.assertEqual(
           1,
           error_collector.Results().count(
               'Do not use namespace using-directives.  '
@@ -3230,11 +3219,11 @@ class CpplintTest(CpplintTestBase):
 
   def testNewlineAtEOF(self):
     def DoTest(self, data, is_missing_eof):
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData('foo.cc', 'cc', data.split('\n'),
                               error_collector)
       # The warning appears only once.
-      self.assertEquals(
+      self.assertEqual(
           int(is_missing_eof),
           error_collector.Results().count(
               'Could not find a newline character at the end of the file.'
@@ -3245,17 +3234,14 @@ class CpplintTest(CpplintTestBase):
 
   def testInvalidUtf8(self):
     def DoTest(self, raw_bytes, has_invalid_utf8):
-      error_collector = ErrorCollector(self.assert_)
-      if sys.version_info < (3,):
-          unidata = unicode(raw_bytes, 'utf8', 'replace').split('\n')
-      else:
-          unidata = str(raw_bytes, 'utf8', 'replace').split('\n')
+      error_collector = ErrorCollector(self.assertTrue)
+      unidata = str(raw_bytes, 'utf8', 'replace').split('\n')
       cpplint.ProcessFileData(
           'foo.cc', 'cc',
           unidata,
           error_collector)
       # The warning appears only once.
-      self.assertEquals(
+      self.assertEqual(
           int(has_invalid_utf8),
           error_collector.Results().count(
               'Line contains invalid UTF-8'
@@ -3271,40 +3257,37 @@ class CpplintTest(CpplintTestBase):
 
   def testBadCharacters(self):
     # Test for NUL bytes only
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('nul.cc', 'cc',
                             ['// Copyright 2014 Your Company.',
                              '\0', ''], error_collector)
-    self.assertEquals(
+    self.assertEqual(
         error_collector.Results(),
         'Line contains NUL byte.  [readability/nul] [5]')
 
     # Make sure both NUL bytes and UTF-8 are caught if they appear on
     # the same line.
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     raw_bytes = codecs_latin_encode('\xe9x\0')
-    if sys.version_info < (3,):
-      unidata = unicode(raw_bytes, 'utf8', 'replace')
-    else:
-      unidata = str(raw_bytes, 'utf8', 'replace')
+    unidata = str(raw_bytes, 'utf8', 'replace')
     cpplint.ProcessFileData(
         'nul_utf8.cc', 'cc',
         ['// Copyright 2014 Your Company.',
          unidata,
          ''],
         error_collector)
-    self.assertEquals(
+    self.assertEqual(
         error_collector.Results(),
         ['Line contains invalid UTF-8 (or Unicode replacement character).'
          '  [readability/utf8] [5]',
          'Line contains NUL byte.  [readability/nul] [5]'])
 
   def testIsBlankLine(self):
-    self.assert_(cpplint.IsBlankLine(''))
-    self.assert_(cpplint.IsBlankLine(' '))
-    self.assert_(cpplint.IsBlankLine(' \t\r\n'))
-    self.assert_(not cpplint.IsBlankLine('int a;'))
-    self.assert_(not cpplint.IsBlankLine('{'))
+    self.assertTrue(cpplint.IsBlankLine(''))
+    self.assertTrue(cpplint.IsBlankLine(' '))
+    self.assertTrue(cpplint.IsBlankLine(' \t\r\n'))
+    self.assertTrue(not cpplint.IsBlankLine('int a;'))
+    self.assertTrue(not cpplint.IsBlankLine('{'))
 
   def testBlankLinesCheck(self):
     self.TestBlankLinesCheck(['{\n', '\n', '\n', '}\n'], 1, 1)
@@ -3323,7 +3306,7 @@ class CpplintTest(CpplintTestBase):
         ['int x(\n', '   int a) {\n', '\n', 'return 0;\n', '}'], 1, 0)
 
   def testAllowBlankLineBeforeClosingNamespace(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['namespace {',
                              '',
@@ -3343,12 +3326,12 @@ class CpplintTest(CpplintTestBase):
                              '', '', '', '',
                              '}'],
                             error_collector)
-    self.assertEquals(0, error_collector.Results().count(
+    self.assertEqual(0, error_collector.Results().count(
         'Redundant blank line at the end of a code block should be deleted.'
         '  [whitespace/blank_line] [3]'))
 
   def testAllowBlankLineBeforeIfElseChain(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['if (hoge) {',
                              '',  # No warning
@@ -3360,12 +3343,12 @@ class CpplintTest(CpplintTestBase):
                              '',  # Warning on this line
                              '}'],
                             error_collector)
-    self.assertEquals(1, error_collector.Results().count(
+    self.assertEqual(1, error_collector.Results().count(
         'Redundant blank line at the end of a code block should be deleted.'
         '  [whitespace/blank_line] [3]'))
 
   def testAllowBlankLineAfterExtern(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['extern "C" {',
                              '',
@@ -3373,15 +3356,15 @@ class CpplintTest(CpplintTestBase):
                              '',
                              '}'],
                             error_collector)
-    self.assertEquals(0, error_collector.Results().count(
+    self.assertEqual(0, error_collector.Results().count(
         'Redundant blank line at the start of a code block should be deleted.'
         '  [whitespace/blank_line] [2]'))
-    self.assertEquals(0, error_collector.Results().count(
+    self.assertEqual(0, error_collector.Results().count(
         'Redundant blank line at the end of a code block should be deleted.'
         '  [whitespace/blank_line] [3]'))
 
   def testBlankLineBeforeSectionKeyword(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['class A {',
                              ' public:',
@@ -3409,15 +3392,15 @@ class CpplintTest(CpplintTestBase):
                              '  int a;\\',
                              '};'],
                             error_collector)
-    self.assertEquals(2, error_collector.Results().count(
+    self.assertEqual(2, error_collector.Results().count(
         '"private:" should be preceded by a blank line'
         '  [whitespace/blank_line] [3]'))
-    self.assertEquals(1, error_collector.Results().count(
+    self.assertEqual(1, error_collector.Results().count(
         '"protected:" should be preceded by a blank line'
         '  [whitespace/blank_line] [3]'))
 
   def testNoBlankLineAfterSectionKeyword(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['class A {',
                              ' public:',
@@ -3430,18 +3413,18 @@ class CpplintTest(CpplintTestBase):
                              '  };',
                              '};'],
                             error_collector)
-    self.assertEquals(1, error_collector.Results().count(
+    self.assertEqual(1, error_collector.Results().count(
         'Do not leave a blank line after "public:"'
         '  [whitespace/blank_line] [3]'))
-    self.assertEquals(1, error_collector.Results().count(
+    self.assertEqual(1, error_collector.Results().count(
         'Do not leave a blank line after "protected:"'
         '  [whitespace/blank_line] [3]'))
-    self.assertEquals(1, error_collector.Results().count(
+    self.assertEqual(1, error_collector.Results().count(
         'Do not leave a blank line after "private:"'
         '  [whitespace/blank_line] [3]'))
 
   def testAllowBlankLinesInRawStrings(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['// Copyright 2014 Your Company.',
                              'static const char *kData[] = {R"(',
@@ -3451,10 +3434,10 @@ class CpplintTest(CpplintTestBase):
                              ')"};',
                              ''],
                             error_collector)
-    self.assertEquals('', error_collector.Results())
+    self.assertEqual('', error_collector.Results())
 
   def testElseOnSameLineAsClosingBraces(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['if (hoge) {',
                              '}',
@@ -3464,11 +3447,11 @@ class CpplintTest(CpplintTestBase):
                              '',
                              '}'],
                             error_collector)
-    self.assertEquals(2, error_collector.Results().count(
+    self.assertEqual(2, error_collector.Results().count(
         'An else should appear on the same line as the preceding }'
         '  [whitespace/newline] [4]'))
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['if (hoge) {',
                              '',
@@ -3478,23 +3461,23 @@ class CpplintTest(CpplintTestBase):
                              '',
                              '}'],
                             error_collector)
-    self.assertEquals(1, error_collector.Results().count(
+    self.assertEqual(1, error_collector.Results().count(
         'An else should appear on the same line as the preceding }'
         '  [whitespace/newline] [4]'))
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['if (hoge) {',
                              '',
                              '}',
                              'else_function();'],
                             error_collector)
-    self.assertEquals(0, error_collector.Results().count(
+    self.assertEqual(0, error_collector.Results().count(
         'An else should appear on the same line as the preceding }'
         '  [whitespace/newline] [4]'))
 
   def testMultipleStatementsOnSameLine(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['for (int i = 0; i < 1; i++) {}',
                              'switch (x) {',
@@ -3502,7 +3485,7 @@ class CpplintTest(CpplintTestBase):
                              '}',
                              'sum += MathUtil::SafeIntRound(x); x += 0.1;'],
                             error_collector)
-    self.assertEquals(0, error_collector.Results().count(
+    self.assertEqual(0, error_collector.Results().count(
         'More than one command on the same line  [whitespace/newline] [0]'))
 
     old_verbose_level = cpplint._cpplint_state.verbose_level
@@ -3513,7 +3496,7 @@ class CpplintTest(CpplintTestBase):
     cpplint._cpplint_state.verbose_level = old_verbose_level
 
   def testLambdasOnSameLine(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     old_verbose_level = cpplint._cpplint_state.verbose_level
     cpplint._cpplint_state.verbose_level = 0
     cpplint.ProcessFileData('foo.cc', 'cc',
@@ -3521,10 +3504,10 @@ class CpplintTest(CpplintTestBase):
                               '[](const int i) { return i; };'],
                             error_collector)
     cpplint._cpplint_state.verbose_level = old_verbose_level
-    self.assertEquals(0, error_collector.Results().count(
+    self.assertEqual(0, error_collector.Results().count(
         'More than one command on the same line  [whitespace/newline] [0]'))
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     old_verbose_level = cpplint._cpplint_state.verbose_level
     cpplint._cpplint_state.verbose_level = 0
     cpplint.ProcessFileData('foo.cc', 'cc',
@@ -3533,10 +3516,10 @@ class CpplintTest(CpplintTestBase):
                               '[](const int i) { return i > 0; });'],
                             error_collector)
     cpplint._cpplint_state.verbose_level = old_verbose_level
-    self.assertEquals(0, error_collector.Results().count(
+    self.assertEqual(0, error_collector.Results().count(
         'More than one command on the same line  [whitespace/newline] [0]'))
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     old_verbose_level = cpplint._cpplint_state.verbose_level
     cpplint._cpplint_state.verbose_level = 0
     cpplint.ProcessFileData('foo.cc', 'cc',
@@ -3545,10 +3528,10 @@ class CpplintTest(CpplintTestBase):
                               'this->ReadUnlock(); });'],
                             error_collector)
     cpplint._cpplint_state.verbose_level = old_verbose_level
-    self.assertEquals(0, error_collector.Results().count(
+    self.assertEqual(0, error_collector.Results().count(
         'More than one command on the same line  [whitespace/newline] [0]'))
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     old_verbose_level = cpplint._cpplint_state.verbose_level
     cpplint._cpplint_state.verbose_level = 0
     cpplint.ProcessFileData('foo.cc', 'cc',
@@ -3557,11 +3540,11 @@ class CpplintTest(CpplintTestBase):
                               'this->ReadUnlock(); }, object);'],
                             error_collector)
     cpplint._cpplint_state.verbose_level = old_verbose_level
-    self.assertEquals(0, error_collector.Results().count(
+    self.assertEqual(0, error_collector.Results().count(
         'More than one command on the same line  [whitespace/newline] [0]'))
 
   def testEndOfNamespaceComments(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['namespace {',
                              '',
@@ -3604,26 +3587,26 @@ class CpplintTest(CpplintTestBase):
                             ['}  /* namespace c_style. */ \\',
                              ';'],
                             error_collector)
-    self.assertEquals(1, error_collector.Results().count(
+    self.assertEqual(1, error_collector.Results().count(
         'Namespace should be terminated with "// namespace expected"'
         '  [readability/namespace] [5]'))
-    self.assertEquals(1, error_collector.Results().count(
+    self.assertEqual(1, error_collector.Results().count(
         'Namespace should be terminated with "// namespace outer"'
         '  [readability/namespace] [5]'))
-    self.assertEquals(1, error_collector.Results().count(
+    self.assertEqual(1, error_collector.Results().count(
         'Namespace should be terminated with "// namespace nested"'
         '  [readability/namespace] [5]'))
-    self.assertEquals(3, error_collector.Results().count(
+    self.assertEqual(3, error_collector.Results().count(
         'Anonymous namespace should be terminated with "// namespace"'
         '  [readability/namespace] [5]'))
-    self.assertEquals(2, error_collector.Results().count(
+    self.assertEqual(2, error_collector.Results().count(
         'Anonymous namespace should be terminated with "// namespace" or'
         ' "// anonymous namespace"'
         '  [readability/namespace] [5]'))
-    self.assertEquals(1, error_collector.Results().count(
+    self.assertEqual(1, error_collector.Results().count(
         'Namespace should be terminated with "// namespace missing_comment"'
         '  [readability/namespace] [5]'))
-    self.assertEquals(0, error_collector.Results().count(
+    self.assertEqual(0, error_collector.Results().count(
         'Namespace should be terminated with "// namespace no_warning"'
         '  [readability/namespace] [5]'))
 
@@ -4088,38 +4071,38 @@ class CpplintTest(CpplintTestBase):
                         ['--filter=+a,b,-c'])
       self.assertRaises(SystemExit, cpplint.ParseArguments, ['--headers'])
 
-      self.assertEquals(['foo.cc'], cpplint.ParseArguments(['foo.cc']))
-      self.assertEquals(old_output_format, cpplint._cpplint_state.output_format)
-      self.assertEquals(old_verbose_level, cpplint._cpplint_state.verbose_level)
+      self.assertEqual(['foo.cc'], cpplint.ParseArguments(['foo.cc']))
+      self.assertEqual(old_output_format, cpplint._cpplint_state.output_format)
+      self.assertEqual(old_verbose_level, cpplint._cpplint_state.verbose_level)
 
-      self.assertEquals(['foo.cc'],
+      self.assertEqual(['foo.cc'],
                         cpplint.ParseArguments(['--v=1', 'foo.cc']))
-      self.assertEquals(1, cpplint._cpplint_state.verbose_level)
-      self.assertEquals(['foo.h'],
+      self.assertEqual(1, cpplint._cpplint_state.verbose_level)
+      self.assertEqual(['foo.h'],
                         cpplint.ParseArguments(['--v=3', 'foo.h']))
-      self.assertEquals(3, cpplint._cpplint_state.verbose_level)
-      self.assertEquals(['foo.cpp'],
+      self.assertEqual(3, cpplint._cpplint_state.verbose_level)
+      self.assertEqual(['foo.cpp'],
                         cpplint.ParseArguments(['--verbose=5', 'foo.cpp']))
-      self.assertEquals(5, cpplint._cpplint_state.verbose_level)
+      self.assertEqual(5, cpplint._cpplint_state.verbose_level)
       self.assertRaises(ValueError,
                         cpplint.ParseArguments, ['--v=f', 'foo.cc'])
 
-      self.assertEquals(['foo.cc'],
+      self.assertEqual(['foo.cc'],
                         cpplint.ParseArguments(['--output=emacs', 'foo.cc']))
-      self.assertEquals('emacs', cpplint._cpplint_state.output_format)
-      self.assertEquals(['foo.h'],
+      self.assertEqual('emacs', cpplint._cpplint_state.output_format)
+      self.assertEqual(['foo.h'],
                         cpplint.ParseArguments(['--output=vs7', 'foo.h']))
-      self.assertEquals('vs7', cpplint._cpplint_state.output_format)
+      self.assertEqual('vs7', cpplint._cpplint_state.output_format)
       self.assertRaises(SystemExit,
                         cpplint.ParseArguments, ['--output=blah', 'foo.cc'])
 
       filt = '-,+whitespace,-whitespace/indent'
-      self.assertEquals(['foo.h'],
+      self.assertEqual(['foo.h'],
                         cpplint.ParseArguments(['--filter='+filt, 'foo.h']))
-      self.assertEquals(['-', '+whitespace', '-whitespace/indent'],
+      self.assertEqual(['-', '+whitespace', '-whitespace/indent'],
                         cpplint._cpplint_state.filters)
 
-      self.assertEquals(['foo.cc', 'foo.h'],
+      self.assertEqual(['foo.cc', 'foo.h'],
                         cpplint.ParseArguments(['foo.cc', 'foo.h']))
 
       cpplint._hpp_headers = old_headers
@@ -4174,7 +4157,7 @@ class CpplintTest(CpplintTestBase):
                   os.path.join('src', 'nested', 'three.cpp')]
       cpplint._excludes = None
       actual = cpplint.ParseArguments(['--recursive', 'one.cpp', 'src'])
-      self.assertEquals(set(expected), set(actual))
+      self.assertEqual(set(expected), set(actual))
     finally:
         os.chdir(working_dir)
         shutil.rmtree(temp_dir)
@@ -4193,7 +4176,7 @@ class CpplintTest(CpplintTestBase):
       cpplint._excludes = None
       actual = cpplint.ParseArguments(['--recursive', '--extensions=cpp',
           'one.cpp', 'src'])
-      self.assertEquals(set(expected), set(actual))
+      self.assertEqual(set(expected), set(actual))
     finally:
         os.chdir(working_dir)
         shutil.rmtree(temp_dir)
@@ -4223,23 +4206,23 @@ class CpplintTest(CpplintTestBase):
       ]
       cpplint._excludes = None
       actual = cpplint.ParseArguments(['src'])
-      self.assertEquals(set(['src']), set(actual))
+      self.assertEqual(set(['src']), set(actual))
 
       cpplint._excludes = None
       actual = cpplint.ParseArguments(['--recursive', 'src'])
-      self.assertEquals(set(expected), set(actual))
+      self.assertEqual(set(expected), set(actual))
 
       expected = [os.path.join('src', 'one.cc')]
       cpplint._excludes = None
       actual = cpplint.ParseArguments(['--recursive',
           '--exclude=src{0}t*'.format(os.sep), 'src'])
-      self.assertEquals(set(expected), set(actual))
+      self.assertEqual(set(expected), set(actual))
 
       expected = [os.path.join('src', 'one.cc')]
       cpplint._excludes = None
       actual = cpplint.ParseArguments(['--recursive',
           '--exclude=src/two.cc', '--exclude=src/three.cc', 'src'])
-      self.assertEquals(set(expected), set(actual))
+      self.assertEqual(set(expected), set(actual))
 
       expected = set([
         os.path.join('src2', 'one.cc'),
@@ -4249,7 +4232,7 @@ class CpplintTest(CpplintTestBase):
       cpplint._excludes = None
       actual = cpplint.ParseArguments(['--recursive',
           '--exclude=src', '.'])
-      self.assertEquals(expected, set(actual))
+      self.assertEqual(expected, set(actual))
     finally:
         os.chdir(working_dir)
         shutil.rmtree(temp_dir)
@@ -4262,7 +4245,7 @@ class CpplintTest(CpplintTestBase):
           '<testsuite errors="0" failures="0" name="cpplint" tests="1">'
           '<testcase name="passed" />'
           '</testsuite>')
-      self.assertEquals(expected, cpplint._cpplint_state.FormatJUnitXML())
+      self.assertEqual(expected, cpplint._cpplint_state.FormatJUnitXML())
 
       cpplint._cpplint_state._junit_errors = ['ErrMsg1']
       cpplint._cpplint_state._junit_failures = []
@@ -4270,7 +4253,7 @@ class CpplintTest(CpplintTestBase):
           '<testsuite errors="1" failures="0" name="cpplint" tests="1">'
           '<testcase name="errors"><error>ErrMsg1</error></testcase>'
           '</testsuite>')
-      self.assertEquals(expected, cpplint._cpplint_state.FormatJUnitXML())
+      self.assertEqual(expected, cpplint._cpplint_state.FormatJUnitXML())
 
       cpplint._cpplint_state._junit_errors = ['ErrMsg1', 'ErrMsg2']
       cpplint._cpplint_state._junit_failures = []
@@ -4278,7 +4261,7 @@ class CpplintTest(CpplintTestBase):
           '<testsuite errors="2" failures="0" name="cpplint" tests="2">'
           '<testcase name="errors"><error>ErrMsg1\nErrMsg2</error></testcase>'
           '</testsuite>')
-      self.assertEquals(expected, cpplint._cpplint_state.FormatJUnitXML())
+      self.assertEqual(expected, cpplint._cpplint_state.FormatJUnitXML())
 
       cpplint._cpplint_state._junit_errors = ['ErrMsg']
       cpplint._cpplint_state._junit_failures = [
@@ -4288,7 +4271,7 @@ class CpplintTest(CpplintTestBase):
           '<testcase name="errors"><error>ErrMsg</error></testcase>'
           '<testcase name="File"><failure>5: FailMsg [category/subcategory] '
           '[3]</failure></testcase></testsuite>')
-      self.assertEquals(expected, cpplint._cpplint_state.FormatJUnitXML())
+      self.assertEqual(expected, cpplint._cpplint_state.FormatJUnitXML())
 
       cpplint._cpplint_state._junit_errors = []
       cpplint._cpplint_state._junit_failures = [
@@ -4301,7 +4284,7 @@ class CpplintTest(CpplintTestBase):
           ' [3]\n19: FailMsg3 [category/subcategory] [3]</failure></testcase>'
           '<testcase name="File2"><failure>99: FailMsg2 '
           '[category/subcategory] [3]</failure></testcase></testsuite>')
-      self.assertEquals(expected, cpplint._cpplint_state.FormatJUnitXML())
+      self.assertEqual(expected, cpplint._cpplint_state.FormatJUnitXML())
 
       cpplint._cpplint_state._junit_errors = ['&</error>']
       cpplint._cpplint_state._junit_failures = [
@@ -4312,16 +4295,16 @@ class CpplintTest(CpplintTestBase):
           '</testcase><testcase name="File1"><failure>5: '
           '&amp;&lt;/failure&gt; [category/subcategory] [3]</failure>'
           '</testcase></testsuite>')
-      self.assertEquals(expected, cpplint._cpplint_state.FormatJUnitXML())
+      self.assertEqual(expected, cpplint._cpplint_state.FormatJUnitXML())
 
     finally:
       cpplint._cpplint_state._junit_errors = []
       cpplint._cpplint_state._junit_failures = []
 
   def testQuiet(self):
-    self.assertEquals(cpplint._cpplint_state.quiet, False)
+    self.assertEqual(cpplint._cpplint_state.quiet, False)
     cpplint.ParseArguments(['--quiet', 'one.cpp'])
-    self.assertEquals(cpplint._cpplint_state.quiet, True)
+    self.assertEqual(cpplint._cpplint_state.quiet, True)
 
   def testLineLength(self):
     old_line_length = cpplint._line_length
@@ -4377,7 +4360,7 @@ class CpplintTest(CpplintTestBase):
       cpplint._DEFAULT_FILTERS = default_filters
 
   def testDuplicateHeader(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('path/self.cc', 'cc',
                             ['// Copyright 2014 Your Company. All Rights Reserved.',
                              '#include "path/self.h"',
@@ -4390,7 +4373,7 @@ class CpplintTest(CpplintTestBase):
                              '#endif',
                              ''],
                             error_collector)
-    self.assertEquals(
+    self.assertEqual(
         ['"path/duplicate.h" already included at path/self.cc:3  '
          '[build/include] [4]'],
         error_collector.ResultList())
@@ -4481,7 +4464,7 @@ class CpplintTest(CpplintTestBase):
 
   def GetBuildHeaderGuardPreprocessorSymbol(self, file_path):
     # Figure out the expected header guard by processing an empty file.
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h', [], error_collector)
     for error in error_collector.ResultList():
       matched = re.search(
@@ -4497,9 +4480,9 @@ class CpplintTest(CpplintTestBase):
     self.assertTrue(re.search('MYDIR_FOO_H_$', expected_guard))
 
     # No guard at all: expect one error.
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h', [], error_collector)
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(
             'No #ifndef header guard found, suggested CPP variable is: %s'
@@ -4507,18 +4490,18 @@ class CpplintTest(CpplintTestBase):
         error_collector.ResultList())
 
     # No header guard, but the error is suppressed.
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h',
                             ['// Copyright 2014 Your Company.',
                              '// NOLINT(build/header_guard)', ''],
                             error_collector)
-    self.assertEquals([], error_collector.ResultList())
+    self.assertEqual([], error_collector.ResultList())
 
     # Wrong guard
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h',
                             ['#ifndef FOO_H', '#define FOO_H'], error_collector)
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(
             '#ifndef header guard has wrong style, please use: %s'
@@ -4526,10 +4509,10 @@ class CpplintTest(CpplintTestBase):
         error_collector.ResultList())
 
     # No define
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h',
                             ['#ifndef %s' % expected_guard], error_collector)
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(
             'No #ifndef header guard found, suggested CPP variable is: %s'
@@ -4537,12 +4520,12 @@ class CpplintTest(CpplintTestBase):
         error_collector.ResultList())
 
     # Mismatched define
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h',
                             ['#ifndef %s' % expected_guard,
                              '#define FOO_H'],
                             error_collector)
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(
             'No #ifndef header guard found, suggested CPP variable is: %s'
@@ -4550,13 +4533,13 @@ class CpplintTest(CpplintTestBase):
         error_collector.ResultList())
 
     # No endif
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h',
                             ['#ifndef %s' % expected_guard,
                              '#define %s' % expected_guard,
                              ''],
                             error_collector)
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(
             '#endif line should be "#endif  // %s"'
@@ -4564,13 +4547,13 @@ class CpplintTest(CpplintTestBase):
         error_collector.ResultList())
 
     # Commentless endif
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h',
                             ['#ifndef %s' % expected_guard,
                              '#define %s' % expected_guard,
                              '#endif'],
                             error_collector)
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(
             '#endif line should be "#endif  // %s"'
@@ -4578,13 +4561,13 @@ class CpplintTest(CpplintTestBase):
         error_collector.ResultList())
 
     # Commentless endif for old-style guard
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h',
                             ['#ifndef %s_' % expected_guard,
                              '#define %s_' % expected_guard,
                              '#endif'],
                             error_collector)
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(
             '#endif line should be "#endif  // %s"'
@@ -4592,7 +4575,7 @@ class CpplintTest(CpplintTestBase):
         error_collector.ResultList())
 
     # No header guard errors
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h',
                             ['#ifndef %s' % expected_guard,
                              '#define %s' % expected_guard,
@@ -4603,7 +4586,7 @@ class CpplintTest(CpplintTestBase):
         self.fail('Unexpected error: %s' % line)
 
     # No header guard errors for old-style guard
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h',
                             ['#ifndef %s_' % expected_guard,
                              '#define %s_' % expected_guard,
@@ -4617,13 +4600,13 @@ class CpplintTest(CpplintTestBase):
     try:
       cpplint._cpplint_state.verbose_level = 0
       # Warn on old-style guard if verbosity is 0.
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData(file_path, 'h',
                               ['#ifndef %s_' % expected_guard,
                                '#define %s_' % expected_guard,
                                '#endif  // %s_' % expected_guard],
                               error_collector)
-      self.assertEquals(
+      self.assertEqual(
           1,
           error_collector.ResultList().count(
               '#ifndef header guard has wrong style, please use: %s'
@@ -4633,19 +4616,19 @@ class CpplintTest(CpplintTestBase):
       cpplint._cpplint_state.verbose_level = old_verbose_level
 
     # Completely incorrect header guard
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h',
                             ['#ifndef FOO',
                              '#define FOO',
                              '#endif  // FOO'],
                             error_collector)
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(
             '#ifndef header guard has wrong style, please use: %s'
             '  [build/header_guard] [5]' % expected_guard),
         error_collector.ResultList())
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(
             '#endif line should be "#endif  // %s"'
@@ -4653,19 +4636,19 @@ class CpplintTest(CpplintTestBase):
         error_collector.ResultList())
 
     # incorrect header guard with nolint
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'h',
                             ['#ifndef FOO  // NOLINT',
                              '#define FOO',
                              '#endif  // FOO NOLINT'],
                             error_collector)
-    self.assertEquals(
+    self.assertEqual(
         0,
         error_collector.ResultList().count(
             '#ifndef header guard has wrong style, please use: %s'
             '  [build/header_guard] [5]' % expected_guard),
         error_collector.ResultList())
-    self.assertEquals(
+    self.assertEqual(
         0,
         error_collector.ResultList().count(
             '#endif line should be "#endif  // %s"'
@@ -4674,11 +4657,11 @@ class CpplintTest(CpplintTestBase):
 
     # Special case for flymake
     for test_file in ['mydir/foo_flymake.h', 'mydir/.flymake/foo.h']:
-      error_collector = ErrorCollector(self.assert_)
+      error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData(test_file, 'h',
                               ['// Copyright 2014 Your Company.', ''],
                               error_collector)
-      self.assertEquals(
+      self.assertEqual(
           1,
           error_collector.ResultList().count(
               'No #ifndef header guard found, suggested CPP variable is: %s'
@@ -4688,19 +4671,19 @@ class CpplintTest(CpplintTestBase):
     # Cuda guard
     file_path = 'mydir/foo.cuh'
     expected_guard = self.GetBuildHeaderGuardPreprocessorSymbol(file_path)
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'cuh',
                             ['#ifndef FOO',
                              '#define FOO',
                              '#endif  // FOO'],
                             error_collector)
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(
             '#ifndef header guard has wrong style, please use: %s'
             '  [build/header_guard] [5]' % expected_guard),
         error_collector.ResultList())
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(
             '#endif line should be "#endif  // %s"'
@@ -4708,11 +4691,11 @@ class CpplintTest(CpplintTestBase):
         error_collector.ResultList())
 
   def testPragmaOnce(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('mydir/foo.h', 'h',
         ['// Copyright 2014 Your Company.', '#pragma once', ''],
         error_collector)
-    self.assertEquals([], error_collector.ResultList())
+    self.assertEqual([], error_collector.ResultList())
 
   def testBuildHeaderGuardWithRoot(self):
     temp_directory = os.path.realpath(tempfile.mkdtemp())
@@ -4743,7 +4726,7 @@ class CpplintTest(CpplintTestBase):
       # when the root directory of the repository is properly deduced.
       return
 
-    self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',
+    self.assertEqual('CPPLINT_CPPLINT_TEST_HEADER_H_',
                       cpplint.GetHeaderGuardCPPVariable(file_path))
     #
     # test --root flags:
@@ -4753,7 +4736,7 @@ class CpplintTest(CpplintTestBase):
     # left-strip the header guard by using a root dir inside of the repo dir.
     # relative directory
     cpplint._root = 'cpplint'
-    self.assertEquals('CPPLINT_TEST_HEADER_H_',
+    self.assertEqual('CPPLINT_TEST_HEADER_H_',
                       cpplint.GetHeaderGuardCPPVariable(file_path))
 
     nested_header_directory = os.path.join(header_directory, "nested")
@@ -4763,22 +4746,22 @@ class CpplintTest(CpplintTestBase):
 
     cpplint._root = os.path.join('cpplint', 'nested')
     actual = cpplint.GetHeaderGuardCPPVariable(nested_file_path)
-    self.assertEquals('CPPLINT_TEST_HEADER_H_',
+    self.assertEqual('CPPLINT_TEST_HEADER_H_',
                       actual)
 
     # absolute directory
     # (note that CPPLINT.cfg root=setting is always made absolute)
     cpplint._root = header_directory
-    self.assertEquals('CPPLINT_TEST_HEADER_H_',
+    self.assertEqual('CPPLINT_TEST_HEADER_H_',
                       cpplint.GetHeaderGuardCPPVariable(file_path))
 
     cpplint._root = nested_header_directory
-    self.assertEquals('CPPLINT_TEST_HEADER_H_',
+    self.assertEqual('CPPLINT_TEST_HEADER_H_',
                       cpplint.GetHeaderGuardCPPVariable(nested_file_path))
 
     # --root flag is ignored if an non-existent directory is specified.
     cpplint._root = 'NON_EXISTENT_DIR'
-    self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',
+    self.assertEqual('CPPLINT_CPPLINT_TEST_HEADER_H_',
                       cpplint.GetHeaderGuardCPPVariable(file_path))
 
     # prepend to the header guard by using a root dir that is more outer
@@ -4795,7 +4778,7 @@ class CpplintTest(CpplintTestBase):
     # do not hardcode the 'styleguide' repository name, it could be anything.
     expected_prefix = re.sub(r'[^a-zA-Z0-9]', '_', styleguide_dir_name).upper() + '_'
     # do not have 'styleguide' repo in '/'
-    self.assertEquals('%sCPPLINT_CPPLINT_TEST_HEADER_H_' % (expected_prefix),
+    self.assertEqual('%sCPPLINT_CPPLINT_TEST_HEADER_H_' % (expected_prefix),
                       cpplint.GetHeaderGuardCPPVariable(file_path))
 
     # To run the 'relative path' tests, we must be in the directory of this test file.
@@ -4806,13 +4789,13 @@ class CpplintTest(CpplintTestBase):
     styleguide_rel_path = os.path.relpath(styleguide_path, this_files_path)
     # '..'
     cpplint._root = styleguide_rel_path
-    self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',
+    self.assertEqual('CPPLINT_CPPLINT_TEST_HEADER_H_',
                       cpplint.GetHeaderGuardCPPVariable(file_path))
 
     styleguide_rel_path = os.path.relpath(styleguide_parent_path,
                                           this_files_path)  # '../..'
     cpplint._root = styleguide_rel_path
-    self.assertEquals('%sCPPLINT_CPPLINT_TEST_HEADER_H_' % (expected_prefix),
+    self.assertEqual('%sCPPLINT_CPPLINT_TEST_HEADER_H_' % (expected_prefix),
                       cpplint.GetHeaderGuardCPPVariable(file_path))
 
     cpplint._root = None
@@ -4906,19 +4889,19 @@ class CpplintTest(CpplintTestBase):
       shutil.rmtree(temp_directory)
 
   def testPathSplitToList(self):
-    self.assertEquals([''],
+    self.assertEqual([''],
                       cpplint.PathSplitToList(os.path.join('')))
 
-    self.assertEquals(['.'],
+    self.assertEqual(['.'],
                       cpplint.PathSplitToList(os.path.join('.')))
 
-    self.assertEquals(['..'],
+    self.assertEqual(['..'],
                       cpplint.PathSplitToList(os.path.join('..')))
 
-    self.assertEquals(['..', 'a', 'b'],
+    self.assertEqual(['..', 'a', 'b'],
                       cpplint.PathSplitToList(os.path.join('..', 'a', 'b')))
 
-    self.assertEquals(['a', 'b', 'c', 'd'],
+    self.assertEqual(['a', 'b', 'c', 'd'],
                       cpplint.PathSplitToList(os.path.join('a', 'b', 'c', 'd')))
 
   def testBuildHeaderGuardWithRepository(self):
@@ -4934,31 +4917,31 @@ class CpplintTest(CpplintTestBase):
       open(file_path, 'a').close()
 
       # search for .svn if _repository is not specified
-      self.assertEquals('TRUNK_CPPLINT_CPPLINT_TEST_HEADER_H_',
+      self.assertEqual('TRUNK_CPPLINT_CPPLINT_TEST_HEADER_H_',
                         cpplint.GetHeaderGuardCPPVariable(file_path))
 
       # use the provided repository root for header guards
       cpplint._repository = os.path.relpath(trunk_dir)
-      self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',
+      self.assertEqual('CPPLINT_CPPLINT_TEST_HEADER_H_',
                         cpplint.GetHeaderGuardCPPVariable(file_path))
       cpplint._repository = os.path.abspath(trunk_dir)
-      self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',
+      self.assertEqual('CPPLINT_CPPLINT_TEST_HEADER_H_',
                         cpplint.GetHeaderGuardCPPVariable(file_path))
 
       # ignore _repository if it doesnt exist
       cpplint._repository = os.path.join(temp_directory, 'NON_EXISTANT')
-      self.assertEquals('TRUNK_CPPLINT_CPPLINT_TEST_HEADER_H_',
+      self.assertEqual('TRUNK_CPPLINT_CPPLINT_TEST_HEADER_H_',
                         cpplint.GetHeaderGuardCPPVariable(file_path))
 
       # ignore _repository if it exists but file isn't in it
       cpplint._repository = os.path.relpath(temp_directory2)
-      self.assertEquals('TRUNK_CPPLINT_CPPLINT_TEST_HEADER_H_',
+      self.assertEqual('TRUNK_CPPLINT_CPPLINT_TEST_HEADER_H_',
                         cpplint.GetHeaderGuardCPPVariable(file_path))
 
       # _root should be relative to _repository
       cpplint._repository = os.path.relpath(trunk_dir)
       cpplint._root = 'cpplint'
-      self.assertEquals('CPPLINT_TEST_HEADER_H_',
+      self.assertEqual('CPPLINT_TEST_HEADER_H_',
                         cpplint.GetHeaderGuardCPPVariable(file_path))
 
     finally:
@@ -4988,7 +4971,7 @@ class CpplintTest(CpplintTestBase):
     self.TestLanguageRulesCheck('foo.h', code, '')
 
   def testBuildPrintfFormat(self):
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(
         'foo.cc', 'cc',
         [r'printf("\%%d", value);',
@@ -4996,22 +4979,23 @@ class CpplintTest(CpplintTestBase):
          r'fprintf(file, "\(%d", value);',
          r'vsnprintf(buffer, sizeof(buffer), "\\\{%d", ap);'],
         error_collector)
-    self.assertEquals(
+    self.assertEqual(
         4,
         error_collector.Results().count(
             '%, [, (, and { are undefined character escapes.  Unescape them.'
             '  [build/printf_format] [3]'))
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(
         'foo.cc', 'cc',
         ['// Copyright 2014 Your Company.',
+         '#include <cstdio>',
          r'printf("\\%%%d", value);',
          r'printf(R"(\[)");',
          r'printf(R"(\[%s)", R"(\])");',
          ''],
         error_collector)
-    self.assertEquals('', error_collector.Results())
+    self.assertEqual('', error_collector.Results())
 
   def testRuntimePrintfFormat(self):
     self.TestLint(
@@ -5121,29 +5105,29 @@ class CpplintTest(CpplintTestBase):
     file_path = 'mydir/googleclient/foo.cc'
 
     # There should be a copyright message in the first 10 lines
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'cc', [], error_collector)
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(legal_copyright_message))
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(
         file_path, 'cc',
         ['' for unused_i in range(10)] + [copyright_line],
         error_collector)
-    self.assertEquals(
+    self.assertEqual(
         1,
         error_collector.ResultList().count(legal_copyright_message))
 
     # Test that warning isn't issued if Copyright line appears early enough.
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(file_path, 'cc', [copyright_line], error_collector)
     for message in error_collector.ResultList():
       if message.find('legal/copyright') != -1:
         self.fail('Unexpected error: %s' % message)
 
-    error_collector = ErrorCollector(self.assert_)
+    error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(
         file_path, 'cc',
         ['' for unused_i in range(9)] + [copyright_line],
@@ -5179,18 +5163,18 @@ class Cxx11Test(CpplintTestBase):
     lines.append('')
 
     # Process the file and check resulting error count.
-    collector = ErrorCollector(self.assert_)
+    collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData(filename, extension, lines, collector)
     error_list = collector.ResultList()
-    self.assertEquals(count, len(error_list), error_list)
+    self.assertEqual(count, len(error_list), error_list)
 
   def TestCxx11Feature(self, code, expected_error):
     lines = code.split('\n')
-    collector = ErrorCollector(self.assert_)
+    collector = ErrorCollector(self.assertTrue)
     cpplint.RemoveMultiLineComments('foo.h', lines, collector)
     clean_lines = cpplint.CleansedLines(lines)
     cpplint.FlagCxx11Features('foo.cc', clean_lines, 0, collector)
-    self.assertEquals(expected_error, collector.Results())
+    self.assertEqual(expected_error, collector.Results())
 
   def testBlockedHeaders(self):
     self.TestCxx11Feature('#include <tr1/regex>',
@@ -5244,11 +5228,11 @@ class Cxx14Test(CpplintTestBase):
 
   def TestCxx14Feature(self, code, expected_error):
     lines = code.split('\n')
-    collector = ErrorCollector(self.assert_)
+    collector = ErrorCollector(self.assertTrue)
     cpplint.RemoveMultiLineComments('foo.h', lines, collector)
     clean_lines = cpplint.CleansedLines(lines)
     cpplint.FlagCxx14Features('foo.cc', clean_lines, 0, collector)
-    self.assertEquals(expected_error, collector.Results())
+    self.assertEqual(expected_error, collector.Results())
 
   def testBlockedHeaders(self):
     self.TestCxx14Feature('#include <scoped_allocator>',
@@ -5261,6 +5245,9 @@ class Cxx14Test(CpplintTestBase):
 
 class CleansedLinesTest(unittest.TestCase):
 
+  def setUp(self):
+    self.assertEqual = self.assertEqual
+
   def testInit(self):
     lines = ['Line 1',
              'Line 2',
@@ -5269,17 +5256,17 @@ class CleansedLinesTest(unittest.TestCase):
              'Line 5 "foo"']
 
     clean_lines = cpplint.CleansedLines(lines)
-    self.assertEquals(lines, clean_lines.raw_lines)
-    self.assertEquals(5, clean_lines.NumLines())
+    self.assertEqual(lines, clean_lines.raw_lines)
+    self.assertEqual(5, clean_lines.NumLines())
 
-    self.assertEquals(['Line 1',
+    self.assertEqual(['Line 1',
                        'Line 2',
                        'Line 3',
                        'Line 4',
                        'Line 5 "foo"'],
                       clean_lines.lines)
 
-    self.assertEquals(['Line 1',
+    self.assertEqual(['Line 1',
                        'Line 2',
                        'Line 3',
                        'Line 4',
@@ -5288,48 +5275,48 @@ class CleansedLinesTest(unittest.TestCase):
 
   def testInitEmpty(self):
     clean_lines = cpplint.CleansedLines([])
-    self.assertEquals([], clean_lines.raw_lines)
-    self.assertEquals(0, clean_lines.NumLines())
+    self.assertEqual([], clean_lines.raw_lines)
+    self.assertEqual(0, clean_lines.NumLines())
 
   def testCollapseStrings(self):
     collapse = cpplint.CleansedLines._CollapseStrings
-    self.assertEquals('""', collapse('""'))             # ""     (empty)
-    self.assertEquals('"""', collapse('"""'))           # """    (bad)
-    self.assertEquals('""', collapse('"xyz"'))          # "xyz"  (string)
-    self.assertEquals('""', collapse('"\\\""'))         # "\""   (string)
-    self.assertEquals('""', collapse('"\'"'))           # "'"    (string)
-    self.assertEquals('"\"', collapse('"\"'))           # "\"    (bad)
-    self.assertEquals('""', collapse('"\\\\"'))         # "\\"   (string)
-    self.assertEquals('"', collapse('"\\\\\\"'))        # "\\\"  (bad)
-    self.assertEquals('""', collapse('"\\\\\\\\"'))     # "\\\\" (string)
-
-    self.assertEquals('\'\'', collapse('\'\''))         # ''     (empty)
-    self.assertEquals('\'\'', collapse('\'a\''))        # 'a'    (char)
-    self.assertEquals('\'\'', collapse('\'\\\'\''))     # '\''   (char)
-    self.assertEquals('\'', collapse('\'\\\''))         # '\'    (bad)
-    self.assertEquals('', collapse('\\012'))            # '\012' (char)
-    self.assertEquals('', collapse('\\xfF0'))           # '\xfF0' (char)
-    self.assertEquals('', collapse('\\n'))              # '\n' (char)
-    self.assertEquals(r'\#', collapse('\\#'))           # '\#' (bad)
-
-    self.assertEquals('"" + ""', collapse('"\'" + "\'"'))
-    self.assertEquals("'', ''", collapse("'\"', '\"'"))
-    self.assertEquals('""[0b10]', collapse('"a\'b"[0b1\'0]'))
-
-    self.assertEquals('42', collapse("4'2"))
-    self.assertEquals('0b0101', collapse("0b0'1'0'1"))
-    self.assertEquals('1048576', collapse("1'048'576"))
-    self.assertEquals('0X100000', collapse("0X10'0000"))
-    self.assertEquals('0004000000', collapse("0'004'000'000"))
-    self.assertEquals('1.602176565e-19', collapse("1.602'176'565e-19"))
-    self.assertEquals('\'\' + 0xffff', collapse("'i' + 0xf'f'f'f"))
-    self.assertEquals('sizeof\'\' == 1', collapse("sizeof'x' == 1"))
-    self.assertEquals('0x.03p100', collapse('0x.0\'3p1\'0\'0'))
-    self.assertEquals('123.45', collapse('1\'23.4\'5'))
-
-    self.assertEquals('StringReplace(body, "", "");',
+    self.assertEqual('""', collapse('""'))             # ""     (empty)
+    self.assertEqual('"""', collapse('"""'))           # """    (bad)
+    self.assertEqual('""', collapse('"xyz"'))          # "xyz"  (string)
+    self.assertEqual('""', collapse('"\\\""'))         # "\""   (string)
+    self.assertEqual('""', collapse('"\'"'))           # "'"    (string)
+    self.assertEqual('"\"', collapse('"\"'))           # "\"    (bad)
+    self.assertEqual('""', collapse('"\\\\"'))         # "\\"   (string)
+    self.assertEqual('"', collapse('"\\\\\\"'))        # "\\\"  (bad)
+    self.assertEqual('""', collapse('"\\\\\\\\"'))     # "\\\\" (string)
+
+    self.assertEqual('\'\'', collapse('\'\''))         # ''     (empty)
+    self.assertEqual('\'\'', collapse('\'a\''))        # 'a'    (char)
+    self.assertEqual('\'\'', collapse('\'\\\'\''))     # '\''   (char)
+    self.assertEqual('\'', collapse('\'\\\''))         # '\'    (bad)
+    self.assertEqual('', collapse('\\012'))            # '\012' (char)
+    self.assertEqual('', collapse('\\xfF0'))           # '\xfF0' (char)
+    self.assertEqual('', collapse('\\n'))              # '\n' (char)
+    self.assertEqual(r'\#', collapse('\\#'))           # '\#' (bad)
+
+    self.assertEqual('"" + ""', collapse('"\'" + "\'"'))
+    self.assertEqual("'', ''", collapse("'\"', '\"'"))
+    self.assertEqual('""[0b10]', collapse('"a\'b"[0b1\'0]'))
+
+    self.assertEqual('42', collapse("4'2"))
+    self.assertEqual('0b0101', collapse("0b0'1'0'1"))
+    self.assertEqual('1048576', collapse("1'048'576"))
+    self.assertEqual('0X100000', collapse("0X10'0000"))
+    self.assertEqual('0004000000', collapse("0'004'000'000"))
+    self.assertEqual('1.602176565e-19', collapse("1.602'176'565e-19"))
+    self.assertEqual('\'\' + 0xffff', collapse("'i' + 0xf'f'f'f"))
+    self.assertEqual('sizeof\'\' == 1', collapse("sizeof'x' == 1"))
+    self.assertEqual('0x.03p100', collapse('0x.0\'3p1\'0\'0'))
+    self.assertEqual('123.45', collapse('1\'23.4\'5'))
+
+    self.assertEqual('StringReplace(body, "", "");',
                       collapse('StringReplace(body, "\\\\", "\\\\\\\\");'))
-    self.assertEquals('\'\' ""',
+    self.assertEqual('\'\' ""',
                       collapse('\'"\' "foo"'))
 
 
@@ -5446,7 +5433,7 @@ class OrderOfIncludesTest(CpplintTestBase):
                      classify_include(file_info('foo/foo.cc'),
                                       'string',
                                       False))
-    self.assertEquals(cpplint._OTHER_HEADER,
+    self.assertEqual(cpplint._OTHER_HEADER,
                      classify_include(file_info('foo/foo.cc'),
                                       'boost/any.hpp',
                                       True))
@@ -5645,6 +5632,7 @@ class CheckForFunctionLengthsTest(CpplintTestBase):
 
   def setUp(self):
     # Reducing these thresholds for the tests speeds up tests significantly.
+    CpplintTestBase.setUp(self)
     self.old_normal_trigger = cpplint._FunctionState._NORMAL_TRIGGER
     self.old_test_trigger = cpplint._FunctionState._TEST_TRIGGER
 
@@ -5662,7 +5650,7 @@ class CheckForFunctionLengthsTest(CpplintTestBase):
       code: C++ source code expected to generate a warning message.
       expected_message: Message expected to be generated by the C++ code.
     """
-    self.assertEquals(expected_message,
+    self.assertEqual(expected_message,
                       self.PerformFunctionLengthsCheck(code))
 
   def TriggerLines(self, error_level):
@@ -5996,6 +5984,7 @@ def TrimExtraIndent(text_block):
 class CloseExpressionTest(unittest.TestCase):
 
   def setUp(self):
+    self.assertEqual = self.assertEqual
     self.lines = cpplint.CleansedLines(
         #           1         2         3         4         5
         # 0123456789012345678901234567890123456789012345678901234567890
@@ -6040,7 +6029,7 @@ class CloseExpressionTest(unittest.TestCase):
                  (18, 47, 20, 1)]
     for p in positions:
       (_, line, column) = cpplint.CloseExpression(self.lines, p[0], p[1])
-      self.assertEquals((p[2], p[3]), (line, column))
+      self.assertEqual((p[2], p[3]), (line, column))
 
   def testReverseCloseExpression(self):
     # List of positions to test:
@@ -6060,172 +6049,173 @@ class CloseExpressionTest(unittest.TestCase):
                  (20, 0, 18, 47)]
     for p in positions:
       (_, line, column) = cpplint.ReverseCloseExpression(self.lines, p[0], p[1])
-      self.assertEquals((p[2], p[3]), (line, column))
+      self.assertEqual((p[2], p[3]), (line, column))
 
 
 class NestingStateTest(unittest.TestCase):
 
   def setUp(self):
     self.nesting_state = cpplint.NestingState()
-    self.error_collector = ErrorCollector(self.assert_)
+    self.error_collector = ErrorCollector(self.assertTrue)
+    self.assertEqual = self.assertEqual
 
   def UpdateWithLines(self, lines):
     clean_lines = cpplint.CleansedLines(lines)
-    for line in xrange(clean_lines.NumLines()):
+    for line in range(clean_lines.NumLines()):
       self.nesting_state.Update('test.cc',
                                 clean_lines, line, self.error_collector)
 
   def testEmpty(self):
     self.UpdateWithLines([])
-    self.assertEquals(self.nesting_state.stack, [])
+    self.assertEqual(self.nesting_state.stack, [])
 
   def testNamespace(self):
     self.UpdateWithLines(['namespace {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0],
                                cpplint._NamespaceInfo))
     self.assertTrue(self.nesting_state.stack[0].seen_open_brace)
-    self.assertEquals(self.nesting_state.stack[0].name, '')
+    self.assertEqual(self.nesting_state.stack[0].name, '')
 
     self.UpdateWithLines(['namespace outer { namespace inner'])
-    self.assertEquals(len(self.nesting_state.stack), 3)
+    self.assertEqual(len(self.nesting_state.stack), 3)
     self.assertTrue(self.nesting_state.stack[0].seen_open_brace)
     self.assertTrue(self.nesting_state.stack[1].seen_open_brace)
     self.assertFalse(self.nesting_state.stack[2].seen_open_brace)
-    self.assertEquals(self.nesting_state.stack[0].name, '')
-    self.assertEquals(self.nesting_state.stack[1].name, 'outer')
-    self.assertEquals(self.nesting_state.stack[2].name, 'inner')
+    self.assertEqual(self.nesting_state.stack[0].name, '')
+    self.assertEqual(self.nesting_state.stack[1].name, 'outer')
+    self.assertEqual(self.nesting_state.stack[2].name, 'inner')
 
     self.UpdateWithLines(['{'])
     self.assertTrue(self.nesting_state.stack[2].seen_open_brace)
 
     self.UpdateWithLines(['}', '}}'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
   def testDecoratedClass(self):
     self.UpdateWithLines(['class Decorated_123 API A {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'A')
+    self.assertEqual(self.nesting_state.stack[0].name, 'A')
     self.assertFalse(self.nesting_state.stack[0].is_derived)
-    self.assertEquals(self.nesting_state.stack[0].class_indent, 0)
+    self.assertEqual(self.nesting_state.stack[0].class_indent, 0)
     self.UpdateWithLines(['}'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
   def testInnerClass(self):
     self.UpdateWithLines(['class A::B::C {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'A::B::C')
+    self.assertEqual(self.nesting_state.stack[0].name, 'A::B::C')
     self.assertFalse(self.nesting_state.stack[0].is_derived)
-    self.assertEquals(self.nesting_state.stack[0].class_indent, 0)
+    self.assertEqual(self.nesting_state.stack[0].class_indent, 0)
     self.UpdateWithLines(['}'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
   def testClass(self):
     self.UpdateWithLines(['class A {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'A')
+    self.assertEqual(self.nesting_state.stack[0].name, 'A')
     self.assertFalse(self.nesting_state.stack[0].is_derived)
-    self.assertEquals(self.nesting_state.stack[0].class_indent, 0)
+    self.assertEqual(self.nesting_state.stack[0].class_indent, 0)
 
     self.UpdateWithLines(['};',
                           'struct B : public A {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'B')
+    self.assertEqual(self.nesting_state.stack[0].name, 'B')
     self.assertTrue(self.nesting_state.stack[0].is_derived)
 
     self.UpdateWithLines(['};',
                           'class C',
                           ': public A {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'C')
+    self.assertEqual(self.nesting_state.stack[0].name, 'C')
     self.assertTrue(self.nesting_state.stack[0].is_derived)
 
     self.UpdateWithLines(['};',
                           'template<T>'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
     self.UpdateWithLines(['class D {', '  class E {'])
-    self.assertEquals(len(self.nesting_state.stack), 2)
+    self.assertEqual(len(self.nesting_state.stack), 2)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'D')
+    self.assertEqual(self.nesting_state.stack[0].name, 'D')
     self.assertFalse(self.nesting_state.stack[0].is_derived)
     self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[1].name, 'E')
+    self.assertEqual(self.nesting_state.stack[1].name, 'E')
     self.assertFalse(self.nesting_state.stack[1].is_derived)
-    self.assertEquals(self.nesting_state.stack[1].class_indent, 2)
-    self.assertEquals(self.nesting_state.InnermostClass().name, 'E')
+    self.assertEqual(self.nesting_state.stack[1].class_indent, 2)
+    self.assertEqual(self.nesting_state.InnermostClass().name, 'E')
 
     self.UpdateWithLines(['}', '}'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
   def testClassAccess(self):
     self.UpdateWithLines(['class A {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].access, 'private')
+    self.assertEqual(self.nesting_state.stack[0].access, 'private')
 
     self.UpdateWithLines([' public:'])
-    self.assertEquals(self.nesting_state.stack[0].access, 'public')
+    self.assertEqual(self.nesting_state.stack[0].access, 'public')
     self.UpdateWithLines([' protracted:'])
-    self.assertEquals(self.nesting_state.stack[0].access, 'public')
+    self.assertEqual(self.nesting_state.stack[0].access, 'public')
     self.UpdateWithLines([' protected:'])
-    self.assertEquals(self.nesting_state.stack[0].access, 'protected')
+    self.assertEqual(self.nesting_state.stack[0].access, 'protected')
     self.UpdateWithLines([' private:'])
-    self.assertEquals(self.nesting_state.stack[0].access, 'private')
+    self.assertEqual(self.nesting_state.stack[0].access, 'private')
 
     self.UpdateWithLines(['  struct B {'])
-    self.assertEquals(len(self.nesting_state.stack), 2)
+    self.assertEqual(len(self.nesting_state.stack), 2)
     self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[1].access, 'public')
-    self.assertEquals(self.nesting_state.stack[0].access, 'private')
+    self.assertEqual(self.nesting_state.stack[1].access, 'public')
+    self.assertEqual(self.nesting_state.stack[0].access, 'private')
 
     self.UpdateWithLines(['   protected  :'])
-    self.assertEquals(self.nesting_state.stack[1].access, 'protected')
-    self.assertEquals(self.nesting_state.stack[0].access, 'private')
+    self.assertEqual(self.nesting_state.stack[1].access, 'protected')
+    self.assertEqual(self.nesting_state.stack[0].access, 'private')
 
     self.UpdateWithLines(['  }', '}'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
   def testStruct(self):
     self.UpdateWithLines(['struct A {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'A')
+    self.assertEqual(self.nesting_state.stack[0].name, 'A')
     self.assertFalse(self.nesting_state.stack[0].is_derived)
 
     self.UpdateWithLines(['}',
                           'void Func(struct B arg) {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertFalse(isinstance(self.nesting_state.stack[0],
                                 cpplint._ClassInfo))
 
     self.UpdateWithLines(['}'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
   def testPreprocessor(self):
-    self.assertEquals(len(self.nesting_state.pp_stack), 0)
+    self.assertEqual(len(self.nesting_state.pp_stack), 0)
     self.UpdateWithLines(['#if MACRO1'])
-    self.assertEquals(len(self.nesting_state.pp_stack), 1)
+    self.assertEqual(len(self.nesting_state.pp_stack), 1)
     self.UpdateWithLines(['#endif'])
-    self.assertEquals(len(self.nesting_state.pp_stack), 0)
+    self.assertEqual(len(self.nesting_state.pp_stack), 0)
 
     self.UpdateWithLines(['#ifdef MACRO2'])
-    self.assertEquals(len(self.nesting_state.pp_stack), 1)
+    self.assertEqual(len(self.nesting_state.pp_stack), 1)
     self.UpdateWithLines(['#else'])
-    self.assertEquals(len(self.nesting_state.pp_stack), 1)
+    self.assertEqual(len(self.nesting_state.pp_stack), 1)
     self.UpdateWithLines(['#ifdef MACRO3'])
-    self.assertEquals(len(self.nesting_state.pp_stack), 2)
+    self.assertEqual(len(self.nesting_state.pp_stack), 2)
     self.UpdateWithLines(['#elif MACRO4'])
-    self.assertEquals(len(self.nesting_state.pp_stack), 2)
+    self.assertEqual(len(self.nesting_state.pp_stack), 2)
     self.UpdateWithLines(['#endif'])
-    self.assertEquals(len(self.nesting_state.pp_stack), 1)
+    self.assertEqual(len(self.nesting_state.pp_stack), 1)
     self.UpdateWithLines(['#endif'])
-    self.assertEquals(len(self.nesting_state.pp_stack), 0)
+    self.assertEqual(len(self.nesting_state.pp_stack), 0)
 
     self.UpdateWithLines(['#ifdef MACRO5',
                           'class A {',
@@ -6234,162 +6224,162 @@ class NestingStateTest(unittest.TestCase):
                           '#else',
                           'class C {',
                           '#endif'])
-    self.assertEquals(len(self.nesting_state.pp_stack), 0)
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.pp_stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'A')
+    self.assertEqual(self.nesting_state.stack[0].name, 'A')
     self.UpdateWithLines(['};'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
     self.UpdateWithLines(['class D',
                           '#ifdef MACRO7'])
-    self.assertEquals(len(self.nesting_state.pp_stack), 1)
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.pp_stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'D')
+    self.assertEqual(self.nesting_state.stack[0].name, 'D')
     self.assertFalse(self.nesting_state.stack[0].is_derived)
 
     self.UpdateWithLines(['#elif MACRO8',
                           ': public E'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[0].name, 'D')
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[0].name, 'D')
     self.assertTrue(self.nesting_state.stack[0].is_derived)
     self.assertFalse(self.nesting_state.stack[0].seen_open_brace)
 
     self.UpdateWithLines(['#else',
                           '{'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[0].name, 'D')
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[0].name, 'D')
     self.assertFalse(self.nesting_state.stack[0].is_derived)
     self.assertTrue(self.nesting_state.stack[0].seen_open_brace)
 
     self.UpdateWithLines(['#endif'])
-    self.assertEquals(len(self.nesting_state.pp_stack), 0)
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[0].name, 'D')
+    self.assertEqual(len(self.nesting_state.pp_stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[0].name, 'D')
     self.assertFalse(self.nesting_state.stack[0].is_derived)
     self.assertFalse(self.nesting_state.stack[0].seen_open_brace)
 
     self.UpdateWithLines([';'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
   def testTemplate(self):
     self.UpdateWithLines(['template <T,',
                           '          class Arg1 = tmpl<T> >'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
     self.UpdateWithLines(['class A {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'A')
+    self.assertEqual(self.nesting_state.stack[0].name, 'A')
 
     self.UpdateWithLines(['};',
                           'template <T,',
                           '  template <typename, typename> class B>',
                           'class C'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'C')
+    self.assertEqual(self.nesting_state.stack[0].name, 'C')
     self.UpdateWithLines([';'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
     self.UpdateWithLines(['class D : public Tmpl<E>'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'D')
+    self.assertEqual(self.nesting_state.stack[0].name, 'D')
 
     self.UpdateWithLines(['{', '};'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
     self.UpdateWithLines(['template <class F,',
                           '          class G,',
                           '          class H,',
                           '          typename I>',
                           'static void Func() {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertFalse(isinstance(self.nesting_state.stack[0],
                                 cpplint._ClassInfo))
     self.UpdateWithLines(['}',
                           'template <class J> class K {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'K')
+    self.assertEqual(self.nesting_state.stack[0].name, 'K')
 
   def testTemplateDefaultArg(self):
     self.UpdateWithLines([
       'template <class T, class D = default_delete<T>> class unique_ptr {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(self.nesting_state.stack[0], isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
 
   def testTemplateInnerClass(self):
     self.UpdateWithLines(['class A {',
                           ' public:'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
 
     self.UpdateWithLines(['  template <class B>',
                           '  class C<alloc<B> >',
                           '      : public A {'])
-    self.assertEquals(len(self.nesting_state.stack), 2)
+    self.assertEqual(len(self.nesting_state.stack), 2)
     self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))
 
   def testArguments(self):
     self.UpdateWithLines(['class A {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'A')
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
+    self.assertEqual(self.nesting_state.stack[0].name, 'A')
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 0)
 
     self.UpdateWithLines(['  void Func(',
                           '    struct X arg1,'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 1)
     self.UpdateWithLines(['    struct X *arg2);'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 0)
 
     self.UpdateWithLines(['};'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
     self.UpdateWithLines(['struct B {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
     self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
-    self.assertEquals(self.nesting_state.stack[0].name, 'B')
+    self.assertEqual(self.nesting_state.stack[0].name, 'B')
 
     self.UpdateWithLines(['#ifdef MACRO',
                           '  void Func(',
                           '    struct X arg1'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 1)
     self.UpdateWithLines(['#else'])
 
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 0)
     self.UpdateWithLines(['  void Func(',
                           '    struct X arg1'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 1)
 
     self.UpdateWithLines(['#endif'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 1)
     self.UpdateWithLines(['    struct X *arg2);'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 0)
 
     self.UpdateWithLines(['};'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
   def testInlineAssembly(self):
     self.UpdateWithLines(['void CopyRow_SSE2(const uint8* src, uint8* dst,',
                           '                  int count) {'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
-    self.assertEquals(self.nesting_state.stack[-1].inline_asm, cpplint._NO_ASM)
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 0)
+    self.assertEqual(self.nesting_state.stack[-1].inline_asm, cpplint._NO_ASM)
 
     self.UpdateWithLines(['  asm volatile ('])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
-    self.assertEquals(self.nesting_state.stack[-1].inline_asm,
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 1)
+    self.assertEqual(self.nesting_state.stack[-1].inline_asm,
                       cpplint._INSIDE_ASM)
 
     self.UpdateWithLines(['    "sub        %0,%1                         \\n"',
@@ -6406,40 +6396,40 @@ class NestingStateTest(unittest.TestCase):
                           '    "+r"(count)  // %2',
                           '  :',
                           '  : "memory", "cc"'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
-    self.assertEquals(self.nesting_state.stack[-1].inline_asm,
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 1)
+    self.assertEqual(self.nesting_state.stack[-1].inline_asm,
                       cpplint._INSIDE_ASM)
 
     self.UpdateWithLines(['#if defined(__SSE2__)',
                           '    , "xmm0", "xmm1"'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
-    self.assertEquals(self.nesting_state.stack[-1].inline_asm,
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 1)
+    self.assertEqual(self.nesting_state.stack[-1].inline_asm,
                       cpplint._INSIDE_ASM)
 
     self.UpdateWithLines(['#endif'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
-    self.assertEquals(self.nesting_state.stack[-1].inline_asm,
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 1)
+    self.assertEqual(self.nesting_state.stack[-1].inline_asm,
                       cpplint._INSIDE_ASM)
 
     self.UpdateWithLines(['  );'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
-    self.assertEquals(self.nesting_state.stack[-1].inline_asm, cpplint._END_ASM)
+    self.assertEqual(len(self.nesting_state.stack), 1)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 0)
+    self.assertEqual(self.nesting_state.stack[-1].inline_asm, cpplint._END_ASM)
 
     self.UpdateWithLines(['__asm {'])
-    self.assertEquals(len(self.nesting_state.stack), 2)
-    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
-    self.assertEquals(self.nesting_state.stack[-1].inline_asm,
+    self.assertEqual(len(self.nesting_state.stack), 2)
+    self.assertEqual(self.nesting_state.stack[-1].open_parentheses, 0)
+    self.assertEqual(self.nesting_state.stack[-1].inline_asm,
                       cpplint._BLOCK_ASM)
 
     self.UpdateWithLines(['}'])
-    self.assertEquals(len(self.nesting_state.stack), 1)
+    self.assertEqual(len(self.nesting_state.stack), 1)
 
     self.UpdateWithLines(['}'])
-    self.assertEquals(len(self.nesting_state.stack), 0)
+    self.assertEqual(len(self.nesting_state.stack), 0)
 
 
 class QuietTest(unittest.TestCase):
@@ -6450,6 +6440,7 @@ class QuietTest(unittest.TestCase):
     self.python_executable = sys.executable or 'python'
     self.cpplint_test_h = os.path.join(self.this_dir_path,
                                        'cpplint_test_header.h')
+    self.assertEqual = self.assertEqual
     open(self.cpplint_test_h, 'w').close()
 
   def tearDown(self):
@@ -6476,7 +6467,7 @@ class QuietTest(unittest.TestCase):
   def testNonQuietWithErrors(self):
     # This will fail: the test header is missing a copyright and header guard.
     (return_code, output) = self._runCppLint()
-    self.assertEquals(1, return_code)
+    self.assertEqual(1, return_code)
     # Always-on behavior: Print error messages as they come up.
     self.assertIn("[legal/copyright]", output)
     self.assertIn("[build/header_guard]", output)
@@ -6487,7 +6478,7 @@ class QuietTest(unittest.TestCase):
   def testQuietWithErrors(self):
     # When there are errors, behavior is identical to not passing --quiet.
     (return_code, output) = self._runCppLint('--quiet')
-    self.assertEquals(1, return_code)
+    self.assertEqual(1, return_code)
     self.assertIn("[legal/copyright]", output)
     self.assertIn("[build/header_guard]", output)
     # Even though --quiet was used, print these since there were errors.
@@ -6499,7 +6490,7 @@ class QuietTest(unittest.TestCase):
     (return_code, output) = self._runCppLint('--filter=' +
                                                 '-legal/copyright,' +
                                                 '-build/header_guard')
-    self.assertEquals(0, return_code, output)
+    self.assertEqual(0, return_code, output)
     # No cpplint errors are printed since there were no errors.
     self.assertNotIn("[legal/copyright]", output)
     self.assertNotIn("[build/header_guard]", output)
@@ -6513,7 +6504,7 @@ class QuietTest(unittest.TestCase):
                                              '--filter=' +
                                                  '-legal/copyright,' +
                                                  '-build/header_guard')
-    self.assertEquals(0, return_code, output)
+    self.assertEqual(0, return_code, output)
     # No cpplint errors are printed since there were no errors.
     self.assertNotIn("[legal/copyright]", output)
     self.assertNotIn("[build/header_guard]", output)
@@ -6522,11 +6513,11 @@ class QuietTest(unittest.TestCase):
     self.assertNotIn("Done processing", output)
     self.assertNotIn("Total errors found:", output)
     # Output with no errors must be completely blank!
-    self.assertEquals("", output)
+    self.assertEqual("", output)
 
 # class FileFilterTest(unittest.TestCase):
 #   def testFilterExcludedFiles(self):
-#     self.assertEquals([], _FilterExcludedFiles([]))
+#     self.assertEqual([], _FilterExcludedFiles([]))
 
 # pylint: disable=C6409
 def setUp():