Blame SOURCES/python3-buildscripts-tests.patch

28a3cc
diff --git a/SConstruct b/SConstruct
28a3cc
index f949f65475..78eab698b9 100644
28a3cc
--- a/SConstruct
28a3cc
+++ b/SConstruct
28a3cc
@@ -383,7 +383,7 @@ win_version_min_choices = {
28a3cc
 }
28a3cc
 
28a3cc
 add_option('win-version-min',
28a3cc
-    choices=win_version_min_choices.keys(),
28a3cc
+    choices=list(win_version_min_choices.keys()),
28a3cc
     default=None,
28a3cc
     help='minimum Windows version to support',
28a3cc
     type='choice',
28a3cc
@@ -492,7 +492,7 @@ except ValueError as e:
28a3cc
 def variable_shlex_converter(val):
28a3cc
     # If the argument is something other than a string, propogate
28a3cc
     # it literally.
28a3cc
-    if not isinstance(val, basestring):
28a3cc
+    if not isinstance(val, str):
28a3cc
         return val
28a3cc
     parse_mode = get_option('variable-parse-mode')
28a3cc
     if parse_mode == 'auto':
28a3cc
@@ -820,7 +820,7 @@ SConsignFile(str(sconsDataDir.File('sconsign')))
28a3cc
 def printLocalInfo():
28a3cc
     import sys, SCons
28a3cc
     print( "scons version: " + SCons.__version__ )
28a3cc
-    print( "python version: " + " ".join( [ `i` for i in sys.version_info ] ) )
28a3cc
+    print( "python version: " + " ".join( [ str(i) for i in sys.version_info ] ) )
28a3cc
 
28a3cc
 printLocalInfo()
28a3cc
 
28a3cc
@@ -1930,7 +1930,7 @@ def doConfigure(myenv):
28a3cc
         # to make them real errors.
28a3cc
         cloned.Append(CCFLAGS=['-Werror'])
28a3cc
         conf = Configure(cloned, help=False, custom_tests = {
28a3cc
-                'CheckFlag' : lambda(ctx) : CheckFlagTest(ctx, tool, extension, flag)
28a3cc
+                'CheckFlag' : lambda ctx : CheckFlagTest(ctx, tool, extension, flag)
28a3cc
         })
28a3cc
         available = conf.CheckFlag()
28a3cc
         conf.Finish()
28a3cc
@@ -2402,7 +2402,7 @@ def doConfigure(myenv):
28a3cc
             "undefined" : myenv.File("#etc/ubsan.blacklist"),
28a3cc
         }
28a3cc
 
28a3cc
-        blackfiles = set([v for (k, v) in blackfiles_map.iteritems() if k in sanitizer_list])
28a3cc
+        blackfiles = set([v for (k, v) in blackfiles_map.items() if k in sanitizer_list])
28a3cc
         blacklist_options=["-fsanitize-blacklist=%s" % blackfile
28a3cc
                            for blackfile in blackfiles
28a3cc
                            if os.stat(blackfile.path).st_size != 0]
28a3cc
diff --git a/buildscripts/clang_format.py b/buildscripts/clang_format.py
28a3cc
index cf9884d8b1..c0f4140e59 100755
28a3cc
--- a/buildscripts/clang_format.py
28a3cc
+++ b/buildscripts/clang_format.py
28a3cc
@@ -20,7 +20,7 @@ import sys
28a3cc
 import tarfile
28a3cc
 import tempfile
28a3cc
 import threading
28a3cc
-import urllib2
28a3cc
+import urllib.request, urllib.error, urllib.parse
28a3cc
 from distutils import spawn
28a3cc
 from optparse import OptionParser
28a3cc
 from multiprocessing import cpu_count
28a3cc
@@ -96,11 +96,11 @@ def get_clang_format_from_cache_and_extract(url, tarball_ext):
28a3cc
     num_tries = 5
28a3cc
     for attempt in range(num_tries):
28a3cc
         try:
28a3cc
-            resp = urllib2.urlopen(url)
28a3cc
+            resp = urllib.request.urlopen(url)
28a3cc
             with open(temp_tar_file, 'wb') as f:
28a3cc
               f.write(resp.read())
28a3cc
             break
28a3cc
-        except urllib2.URLError:
28a3cc
+        except urllib.error.URLError:
28a3cc
             if attempt == num_tries - 1:
28a3cc
                 raise
28a3cc
             continue
28a3cc
@@ -436,7 +436,7 @@ def reformat_branch(clang_format, commit_prior_to_reformat, commit_after_reforma
28a3cc
 
28a3cc
         # Check if anything needed reformatting, and if so amend the commit
28a3cc
         if not repo.is_working_tree_dirty():
28a3cc
-            print ("Commit %s needed no reformatting" % commit_hash)
28a3cc
+            print("Commit %s needed no reformatting" % commit_hash)
28a3cc
         else:
28a3cc
             repo.commit(["--all", "--amend", "--no-edit"])
28a3cc
 
28a3cc
diff --git a/buildscripts/cpplint.py b/buildscripts/cpplint.py
28a3cc
index c6aa51b7b9..ed9cdb311e 100755
28a3cc
--- a/buildscripts/cpplint.py
28a3cc
+++ b/buildscripts/cpplint.py
28a3cc
@@ -835,7 +835,7 @@ class _CppLintState(object):
28a3cc
 
28a3cc
   def PrintErrorCounts(self):
28a3cc
     """Print a summary of errors by category, and the total."""
28a3cc
-    for category, count in self.errors_by_category.iteritems():
28a3cc
+    for category, count in self.errors_by_category.items():
28a3cc
       sys.stderr.write('Category \'%s\' errors found: %d\n' %
28a3cc
                        (category, count))
28a3cc
     sys.stderr.write('Total errors found: %d\n' % self.error_count)
28a3cc
@@ -1388,7 +1388,7 @@ def FindEndOfExpressionInLine(line, startpos, stack):
28a3cc
     On finding an unclosed expression: (-1, None)
28a3cc
     Otherwise: (-1, new stack at end of this line)
28a3cc
   """
28a3cc
-  for i in xrange(startpos, len(line)):
28a3cc
+  for i in range(startpos, len(line)):
28a3cc
     char = line[i]
28a3cc
     if char in '([{':
28a3cc
       # Found start of parenthesized expression, push to expression stack
28a3cc
@@ -1687,7 +1687,7 @@ def CheckForCopyright(filename, lines, error):
28a3cc
 
28a3cc
   # We'll say it should occur by line 10. Don't forget there's a
28a3cc
   # dummy line at the front.
28a3cc
-  for line in xrange(1, min(len(lines), 11)):
28a3cc
+  for line in range(1, min(len(lines), 11)):
28a3cc
     if re.search(r'Copyright', lines[line], re.I): break
28a3cc
   else:                       # means no copyright line was found
28a3cc
     error(filename, 0, 'legal/copyright', 5,
28a3cc
@@ -1838,7 +1838,7 @@ def CheckForBadCharacters(filename, lines, error):
28a3cc
     error: The function to call with any errors found.
28a3cc
   """
28a3cc
   for linenum, line in enumerate(lines):
28a3cc
-    if u'\ufffd' in line:
28a3cc
+    if '\ufffd' in line:
28a3cc
       error(filename, linenum, 'readability/utf8', 5,
28a3cc
             'Line contains invalid UTF-8 (or Unicode replacement character).')
28a3cc
     if '\0' in line:
28a3cc
@@ -2884,7 +2884,7 @@ def CheckForFunctionLengths(filename, clean_lines, linenum,
28a3cc
 
28a3cc
   if starting_func:
28a3cc
     body_found = False
28a3cc
-    for start_linenum in xrange(linenum, clean_lines.NumLines()):
28a3cc
+    for start_linenum in range(linenum, clean_lines.NumLines()):
28a3cc
       start_line = lines[start_linenum]
28a3cc
       joined_line += ' ' + start_line.lstrip()
28a3cc
       if Search(r'(;|})', start_line):  # Declarations and trivial functions
28a3cc
@@ -3361,7 +3361,7 @@ def CheckBracesSpacing(filename, clean_lines, linenum, error):
28a3cc
     trailing_text = ''
28a3cc
     if endpos > -1:
28a3cc
       trailing_text = endline[endpos:]
28a3cc
-    for offset in xrange(endlinenum + 1,
28a3cc
+    for offset in range(endlinenum + 1,
28a3cc
                          min(endlinenum + 3, clean_lines.NumLines() - 1)):
28a3cc
       trailing_text += clean_lines.elided[offset]
28a3cc
     if not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text):
28a3cc
@@ -3530,7 +3530,7 @@ def IsRValueType(clean_lines, nesting_state, linenum, column):
28a3cc
 
28a3cc
     # Look for the previous 'for(' in the previous lines.
28a3cc
     before_text = match_symbol.group(1)
28a3cc
-    for i in xrange(start - 1, max(start - 6, 0), -1):
28a3cc
+    for i in range(start - 1, max(start - 6, 0), -1):
28a3cc
       before_text = clean_lines.elided[i] + before_text
28a3cc
     if Search(r'for\s*\([^{};]*$', before_text):
28a3cc
       # This is the condition inside a for-loop
28a3cc
@@ -3657,12 +3657,12 @@ def IsRValueAllowed(clean_lines, linenum):
28a3cc
     True if line is within the region where RValue references are allowed.
28a3cc
   """
28a3cc
   # Allow region marked by PUSH/POP macros
28a3cc
-  for i in xrange(linenum, 0, -1):
28a3cc
+  for i in range(linenum, 0, -1):
28a3cc
     line = clean_lines.elided[i]
28a3cc
     if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
28a3cc
       if not line.endswith('PUSH'):
28a3cc
         return False
28a3cc
-      for j in xrange(linenum, clean_lines.NumLines(), 1):
28a3cc
+      for j in range(linenum, clean_lines.NumLines(), 1):
28a3cc
         line = clean_lines.elided[j]
28a3cc
         if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
28a3cc
           return line.endswith('POP')
28a3cc
@@ -4142,7 +4142,7 @@ def CheckCheck(filename, clean_lines, linenum, error):
28a3cc
     expression = lines[linenum][start_pos + 1:end_pos - 1]
28a3cc
   else:
28a3cc
     expression = lines[linenum][start_pos + 1:]
28a3cc
-    for i in xrange(linenum + 1, end_line):
28a3cc
+    for i in range(linenum + 1, end_line):
28a3cc
       expression += lines[i]
28a3cc
     expression += last_line[0:end_pos - 1]
28a3cc
 
28a3cc
@@ -4270,7 +4270,7 @@ def GetLineWidth(line):
28a3cc
     The width of the line in column positions, accounting for Unicode
28a3cc
     combining characters and wide characters.
28a3cc
   """
28a3cc
-  if isinstance(line, unicode):
28a3cc
+  if isinstance(line, str):
28a3cc
     width = 0
28a3cc
     for uc in unicodedata.normalize('NFC', line):
28a3cc
       if unicodedata.east_asian_width(uc) in ('W', 'F'):
28a3cc
@@ -4623,7 +4623,7 @@ def _GetTextInside(text, start_pattern):
28a3cc
 
28a3cc
   # Give opening punctuations to get the matching close-punctuations.
28a3cc
   matching_punctuation = {'(': ')', '{': '}', '[': ']'}
28a3cc
-  closing_punctuation = set(matching_punctuation.itervalues())
28a3cc
+  closing_punctuation = set(matching_punctuation.values())
28a3cc
 
28a3cc
   # Find the position to start extracting text.
28a3cc
   match = re.search(start_pattern, text, re.M)
28a3cc
@@ -4949,7 +4949,7 @@ def IsDerivedFunction(clean_lines, linenum):
28a3cc
     virt-specifier.
28a3cc
   """
28a3cc
   # Scan back a few lines for start of current function
28a3cc
-  for i in xrange(linenum, max(-1, linenum - 10), -1):
28a3cc
+  for i in range(linenum, max(-1, linenum - 10), -1):
28a3cc
     match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i])
28a3cc
     if match:
28a3cc
       # Look for "override" after the matching closing parenthesis
28a3cc
@@ -4970,7 +4970,7 @@ def IsInitializerList(clean_lines, linenum):
28a3cc
     True if current line appears to be inside constructor initializer
28a3cc
     list, False otherwise.
28a3cc
   """
28a3cc
-  for i in xrange(linenum, 1, -1):
28a3cc
+  for i in range(linenum, 1, -1):
28a3cc
     line = clean_lines.elided[i]
28a3cc
     if i == linenum:
28a3cc
       remove_function_body = Match(r'^(.*)\{\s*$', line)
28a3cc
@@ -5066,7 +5066,7 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
28a3cc
           # Found the matching < on an earlier line, collect all
28a3cc
           # pieces up to current line.
28a3cc
           line = ''
28a3cc
-          for i in xrange(startline, linenum + 1):
28a3cc
+          for i in range(startline, linenum + 1):
28a3cc
             line += clean_lines.elided[i].strip()
28a3cc
 
28a3cc
   # Check for non-const references in function parameters.  A single '&' may
28a3cc
@@ -5090,7 +5090,7 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
28a3cc
   # appear inside the second set of parentheses on the current line as
28a3cc
   # opposed to the first set.
28a3cc
   if linenum > 0:
28a3cc
-    for i in xrange(linenum - 1, max(0, linenum - 10), -1):
28a3cc
+    for i in range(linenum - 1, max(0, linenum - 10), -1):
28a3cc
       previous_line = clean_lines.elided[i]
28a3cc
       if not Search(r'[),]\s*$', previous_line):
28a3cc
         break
28a3cc
@@ -5121,7 +5121,7 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
28a3cc
     # Don't see a whitelisted function on this line.  Actually we
28a3cc
     # didn't see any function name on this line, so this is likely a
28a3cc
     # multi-line parameter list.  Try a bit harder to catch this case.
28a3cc
-    for i in xrange(2):
28a3cc
+    for i in range(2):
28a3cc
       if (linenum > i and
28a3cc
           Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
28a3cc
         return
28a3cc
@@ -5283,7 +5283,7 @@ def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
28a3cc
   # Try expanding current context to see if we one level of
28a3cc
   # parentheses inside a macro.
28a3cc
   if linenum > 0:
28a3cc
-    for i in xrange(linenum - 1, max(0, linenum - 5), -1):
28a3cc
+    for i in range(linenum - 1, max(0, linenum - 5), -1):
28a3cc
       context = clean_lines.elided[i] + context
28a3cc
   if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
28a3cc
     return False
28a3cc
@@ -5540,7 +5540,7 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
28a3cc
   required = {}  # A map of header name to linenumber and the template entity.
28a3cc
                  # Example of required: { '<functional>': (1219, 'less<>') }
28a3cc
 
28a3cc
-  for linenum in xrange(clean_lines.NumLines()):
28a3cc
+  for linenum in range(clean_lines.NumLines()):
28a3cc
     line = clean_lines.elided[linenum]
28a3cc
     if not line or line[0] == '#':
28a3cc
       continue
28a3cc
@@ -5589,7 +5589,7 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
28a3cc
 
28a3cc
   # include_dict is modified during iteration, so we iterate over a copy of
28a3cc
   # the keys.
28a3cc
-  header_keys = include_dict.keys()
28a3cc
+  header_keys = list(include_dict.keys())
28a3cc
   for header in header_keys:
28a3cc
     (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
28a3cc
     fullpath = common_path + header
28a3cc
@@ -5684,7 +5684,7 @@ def CheckRedundantVirtual(filename, clean_lines, linenum, error):
28a3cc
   end_col = -1
28a3cc
   end_line = -1
28a3cc
   start_col = len(virtual.group(1))
28a3cc
-  for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())):
28a3cc
+  for start_line in range(linenum, min(linenum + 3, clean_lines.NumLines())):
28a3cc
     line = clean_lines.elided[start_line][start_col:]
28a3cc
     parameter_list = Match(r'^([^(]*)\(', line)
28a3cc
     if parameter_list:
28a3cc
@@ -5699,7 +5699,7 @@ def CheckRedundantVirtual(filename, clean_lines, linenum, error):
28a3cc
 
28a3cc
   # Look for "override" or "final" after the parameter list
28a3cc
   # (possibly on the next few lines).
28a3cc
-  for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())):
28a3cc
+  for i in range(end_line, min(end_line + 3, clean_lines.NumLines())):
28a3cc
     line = clean_lines.elided[i][end_col:]
28a3cc
     match = Search(r'\b(override|final)\b', line)
28a3cc
     if match:
28a3cc
@@ -5926,7 +5926,7 @@ def ProcessFileData(filename, file_extension, lines, error,
28a3cc
 
28a3cc
   RemoveMultiLineComments(filename, lines, error)
28a3cc
   clean_lines = CleansedLines(lines)
28a3cc
-  for line in xrange(clean_lines.NumLines()):
28a3cc
+  for line in range(clean_lines.NumLines()):
28a3cc
     ProcessLine(filename, file_extension, clean_lines, line,
28a3cc
                 include_state, function_state, nesting_state, error,
28a3cc
                 extra_check_functions)
28a3cc
diff --git a/buildscripts/errorcodes.py b/buildscripts/errorcodes.py
28a3cc
index cc46789907..7351e6a12e 100755
28a3cc
--- a/buildscripts/errorcodes.py
28a3cc
+++ b/buildscripts/errorcodes.py
28a3cc
@@ -5,13 +5,16 @@
28a3cc
 Parses .cpp files for assertions and verifies assertion codes are distinct.
28a3cc
 Optionally replaces zero codes in source code with new distinct values.
28a3cc
 """
28a3cc
+from __future__ import unicode_literals
28a3cc
+import io
28a3cc
 
28a3cc
 import bisect
28a3cc
 import os
28a3cc
 import sys
28a3cc
-import utils
28a3cc
+from . import utils
28a3cc
 from collections import defaultdict, namedtuple
28a3cc
 from optparse import OptionParser
28a3cc
+from functools import reduce
28a3cc
 
28a3cc
 try:
28a3cc
     import regex as re
28a3cc
@@ -66,9 +69,9 @@ def parseSourceFiles( callback ):
28a3cc
 
28a3cc
     for sourceFile in utils.getAllSourceFiles(prefix='src/mongo/'):
28a3cc
         if list_files:
28a3cc
-            print 'scanning file: ' + sourceFile
28a3cc
+            print('scanning file: ' + sourceFile)
28a3cc
 
28a3cc
-        with open(sourceFile) as f:
28a3cc
+        with io.open(sourceFile, encoding="utf-8") as f:
28a3cc
             text = f.read()
28a3cc
 
28a3cc
             if not any([zz in text for zz in quick]):
28a3cc
@@ -159,7 +162,7 @@ def readErrorCodes():
28a3cc
 
28a3cc
     parseSourceFiles( checkDups )
28a3cc
 
28a3cc
-    if seen.has_key("0"):
28a3cc
+    if "0" in seen:
28a3cc
         code = "0"
28a3cc
         bad = seen[code]
28a3cc
         errors.append( bad )
28a3cc
@@ -167,7 +170,7 @@ def readErrorCodes():
28a3cc
         print( "ZERO_CODE:" )
28a3cc
         print( "  %s:%d:%d:%s" % (bad.sourceFile, line, col, bad.lines) )
28a3cc
 
28a3cc
-    for code, locations in dups.items():
28a3cc
+    for code, locations in list(dups.items()):
28a3cc
         print( "DUPLICATE IDS: %s" % code )
28a3cc
         for loc in locations:
28a3cc
             line, col = getLineAndColumnForPosition(loc)
28a3cc
@@ -189,19 +192,19 @@ def replaceBadCodes( errors, nextCode ):
28a3cc
 
28a3cc
     for loc in skip_errors:
28a3cc
         line, col = getLineAndColumnForPosition(loc)
28a3cc
-        print ("SKIPPING NONZERO code=%s: %s:%d:%d"
28a3cc
+        print("SKIPPING NONZERO code=%s: %s:%d:%d"
28a3cc
                 % (loc.code, loc.sourceFile, line, col))
28a3cc
 
28a3cc
     # Dedupe, sort, and reverse so we don't have to update offsets as we go.
28a3cc
     for assertLoc in reversed(sorted(set(zero_errors))):
28a3cc
         (sourceFile, byteOffset, lines, code) = assertLoc
28a3cc
         lineNum, _ = getLineAndColumnForPosition(assertLoc)
28a3cc
-        print "UPDATING_FILE: %s:%s" % (sourceFile, lineNum)
28a3cc
+        print("UPDATING_FILE: %s:%s" % (sourceFile, lineNum))
28a3cc
 
28a3cc
         ln = lineNum - 1
28a3cc
 
28a3cc
         with open(sourceFile, 'r+') as f:
28a3cc
-            print "LINE_%d_BEFORE:%s" % (lineNum, f.readlines()[ln].rstrip())
28a3cc
+            print("LINE_%d_BEFORE:%s" % (lineNum, f.readlines()[ln].rstrip()))
28a3cc
 
28a3cc
             f.seek(0)
28a3cc
             text = f.read()
28a3cc
@@ -212,7 +215,7 @@ def replaceBadCodes( errors, nextCode ):
28a3cc
             f.write(text[byteOffset+1:])
28a3cc
             f.seek(0)
28a3cc
 
28a3cc
-            print "LINE_%d_AFTER :%s" % (lineNum, f.readlines()[ln].rstrip())
28a3cc
+            print("LINE_%d_AFTER :%s" % (lineNum, f.readlines()[ln].rstrip()))
28a3cc
         nextCode += 1
28a3cc
 
28a3cc
 
28a3cc
@@ -281,7 +284,7 @@ def main():
28a3cc
     elif options.replace:
28a3cc
         replaceBadCodes(errors, next)
28a3cc
     else:
28a3cc
-        print ERROR_HELP
28a3cc
+        print(ERROR_HELP)
28a3cc
         sys.exit(1)
28a3cc
 
28a3cc
 
28a3cc
diff --git a/buildscripts/eslint.py b/buildscripts/eslint.py
28a3cc
index c1ab04fbab..d5c6aef4fc 100755
28a3cc
--- a/buildscripts/eslint.py
28a3cc
+++ b/buildscripts/eslint.py
28a3cc
@@ -18,7 +18,7 @@ import sys
28a3cc
 import tarfile
28a3cc
 import tempfile
28a3cc
 import threading
28a3cc
-import urllib
28a3cc
+import urllib.request, urllib.parse, urllib.error
28a3cc
 from distutils import spawn
28a3cc
 from optparse import OptionParser
28a3cc
 
28a3cc
@@ -81,7 +81,7 @@ def get_eslint_from_cache(dest_file, platform, arch):
28a3cc
     # Download the file
28a3cc
     print("Downloading ESLint %s from %s, saving to %s" % (ESLINT_VERSION,
28a3cc
                                                            url, temp_tar_file))
28a3cc
-    urllib.urlretrieve(url, temp_tar_file)
28a3cc
+    urllib.request.urlretrieve(url, temp_tar_file)
28a3cc
 
28a3cc
     eslint_distfile = ESLINT_SOURCE_TAR_BASE.substitute(platform=platform, arch=arch)
28a3cc
     extract_eslint(temp_tar_file, eslint_distfile)
28a3cc
diff --git a/buildscripts/idl/idl/binder.py b/buildscripts/idl/idl/binder.py
28a3cc
index 354acca974..9612e39305 100644
28a3cc
--- a/buildscripts/idl/idl/binder.py
28a3cc
+++ b/buildscripts/idl/idl/binder.py
28a3cc
@@ -608,7 +608,7 @@ def _validate_enum_int(ctxt, idl_enum):
28a3cc
     min_value = min(int_values_set)
28a3cc
     max_value = max(int_values_set)
28a3cc
 
28a3cc
-    valid_int = {x for x in xrange(min_value, max_value + 1)}
28a3cc
+    valid_int = {x for x in range(min_value, max_value + 1)}
28a3cc
 
28a3cc
     if valid_int != int_values_set:
28a3cc
         ctxt.add_enum_non_continuous_range_error(idl_enum, idl_enum.name)
28a3cc
diff --git a/buildscripts/idl/idl/bson.py b/buildscripts/idl/idl/bson.py
28a3cc
index 214b67a7bf..b84421d657 100644
28a3cc
--- a/buildscripts/idl/idl/bson.py
28a3cc
+++ b/buildscripts/idl/idl/bson.py
28a3cc
@@ -141,7 +141,7 @@ def cpp_bson_type_name(name):
28a3cc
 def list_valid_types():
28a3cc
     # type: () -> List[unicode]
28a3cc
     """Return a list of supported bson types."""
28a3cc
-    return [a for a in _BSON_TYPE_INFORMATION.iterkeys()]
28a3cc
+    return [a for a in _BSON_TYPE_INFORMATION.keys()]
28a3cc
 
28a3cc
 
28a3cc
 def is_valid_bindata_subtype(name):
28a3cc
diff --git a/buildscripts/idl/idl/cpp_types.py b/buildscripts/idl/idl/cpp_types.py
28a3cc
index aafcf87224..e989664eee 100644
28a3cc
--- a/buildscripts/idl/idl/cpp_types.py
28a3cc
+++ b/buildscripts/idl/idl/cpp_types.py
28a3cc
@@ -28,6 +28,7 @@ from . import writer
28a3cc
 
28a3cc
 _STD_ARRAY_UINT8_16 = 'std::array<std::uint8_t,16>'
28a3cc
 
28a3cc
+ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()})
28a3cc
 
28a3cc
 def is_primitive_scalar_type(cpp_type):
28a3cc
     # type: (unicode) -> bool
28a3cc
@@ -75,11 +76,9 @@ def _qualify_array_type(cpp_type):
28a3cc
     return "std::vector<%s>" % (cpp_type)
28a3cc
 
28a3cc
 
28a3cc
-class CppTypeBase(object):
28a3cc
+class CppTypeBase(ABC):
28a3cc
     """Base type for C++ Type information."""
28a3cc
 
28a3cc
-    __metaclass__ = ABCMeta
28a3cc
-
28a3cc
     def __init__(self, field):
28a3cc
         # type: (ast.Field) -> None
28a3cc
         """Construct a CppTypeBase."""
28a3cc
@@ -537,11 +536,9 @@ def get_cpp_type(field):
28a3cc
     return cpp_type_info
28a3cc
 
28a3cc
 
28a3cc
-class BsonCppTypeBase(object):
28a3cc
+class BsonCppTypeBase(ABC):
28a3cc
     """Base type for custom C++ support for BSON Types information."""
28a3cc
 
28a3cc
-    __metaclass__ = ABCMeta
28a3cc
-
28a3cc
     def __init__(self, field):
28a3cc
         # type: (ast.Field) -> None
28a3cc
         """Construct a BsonCppTypeBase."""
28a3cc
diff --git a/buildscripts/idl/idl/enum_types.py b/buildscripts/idl/idl/enum_types.py
28a3cc
index 3caed6f67d..f17c926748 100644
28a3cc
--- a/buildscripts/idl/idl/enum_types.py
28a3cc
+++ b/buildscripts/idl/idl/enum_types.py
28a3cc
@@ -29,11 +29,11 @@ from . import common
28a3cc
 from . import syntax
28a3cc
 from . import writer
28a3cc
 
28a3cc
+ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()})
28a3cc
 
28a3cc
-class EnumTypeInfoBase(object):
28a3cc
-    """Base type for enumeration type information."""
28a3cc
 
28a3cc
-    __metaclass__ = ABCMeta
28a3cc
+class EnumTypeInfoBase(ABC):
28a3cc
+    """Base type for enumeration type information."""
28a3cc
 
28a3cc
     def __init__(self, idl_enum):
28a3cc
         # type: (Union[syntax.Enum,ast.Enum]) -> None
28a3cc
@@ -108,8 +108,6 @@ class EnumTypeInfoBase(object):
28a3cc
 class _EnumTypeInt(EnumTypeInfoBase):
28a3cc
     """Type information for integer enumerations."""
28a3cc
 
28a3cc
-    __metaclass__ = ABCMeta
28a3cc
-
28a3cc
     def __init__(self, idl_enum):
28a3cc
         # type: (Union[syntax.Enum,ast.Enum]) -> None
28a3cc
         super(_EnumTypeInt, self).__init__(idl_enum)
28a3cc
@@ -189,8 +187,6 @@ def _get_constant_enum_name(idl_enum, enum_value):
28a3cc
 class _EnumTypeString(EnumTypeInfoBase):
28a3cc
     """Type information for string enumerations."""
28a3cc
 
28a3cc
-    __metaclass__ = ABCMeta
28a3cc
-
28a3cc
     def __init__(self, idl_enum):
28a3cc
         # type: (Union[syntax.Enum,ast.Enum]) -> None
28a3cc
         super(_EnumTypeString, self).__init__(idl_enum)
28a3cc
diff --git a/buildscripts/idl/idl/generator.py b/buildscripts/idl/idl/generator.py
28a3cc
index 9f591eccc4..8f97abf28c 100644
28a3cc
--- a/buildscripts/idl/idl/generator.py
28a3cc
+++ b/buildscripts/idl/idl/generator.py
28a3cc
@@ -33,6 +33,7 @@ from . import enum_types
28a3cc
 from . import struct_types
28a3cc
 from . import writer
28a3cc
 
28a3cc
+ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()})
28a3cc
 
28a3cc
 def _get_field_member_name(field):
28a3cc
     # type: (ast.Field) -> unicode
28a3cc
@@ -105,11 +106,9 @@ def _get_bson_type_check(bson_element, ctxt_name, field):
28a3cc
         return '%s.checkAndAssertTypes(%s, %s)' % (ctxt_name, bson_element, type_list)
28a3cc
 
28a3cc
 
28a3cc
-class _FieldUsageCheckerBase(object):
28a3cc
+class _FieldUsageCheckerBase(ABC):
28a3cc
     """Check for duplicate fields, and required fields as needed."""
28a3cc
 
28a3cc
-    __metaclass__ = ABCMeta
28a3cc
-
28a3cc
     def __init__(self, indented_writer):
28a3cc
         # type: (writer.IndentedTextWriter) -> None
28a3cc
         """Create a field usage checker."""
28a3cc
@@ -1470,8 +1469,8 @@ def _generate_header(spec, file_name):
28a3cc
     header.generate(spec)
28a3cc
 
28a3cc
     # Generate structs
28a3cc
-    with io.open(file_name, mode='wb') as file_handle:
28a3cc
-        file_handle.write(stream.getvalue().encode())
28a3cc
+    with io.open(file_name, mode='w') as file_handle:
28a3cc
+        file_handle.write(stream.getvalue())
28a3cc
 
28a3cc
 
28a3cc
 def _generate_source(spec, file_name, header_file_name):
28a3cc
@@ -1485,8 +1484,8 @@ def _generate_source(spec, file_name, header_file_name):
28a3cc
     source.generate(spec, header_file_name)
28a3cc
 
28a3cc
     # Generate structs
28a3cc
-    with io.open(file_name, mode='wb') as file_handle:
28a3cc
-        file_handle.write(stream.getvalue().encode())
28a3cc
+    with io.open(file_name, mode='w') as file_handle:
28a3cc
+        file_handle.write(stream.getvalue())
28a3cc
 
28a3cc
 
28a3cc
 def generate_code(spec, output_base_dir, header_file_name, source_file_name):
28a3cc
diff --git a/buildscripts/idl/idl/parser.py b/buildscripts/idl/idl/parser.py
28a3cc
index fd0af9b144..ac36a3a280 100644
28a3cc
--- a/buildscripts/idl/idl/parser.py
28a3cc
+++ b/buildscripts/idl/idl/parser.py
28a3cc
@@ -30,6 +30,7 @@ from . import common
28a3cc
 from . import errors
28a3cc
 from . import syntax
28a3cc
 
28a3cc
+ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()})
28a3cc
 
28a3cc
 class _RuleDesc(object):
28a3cc
     """
28a3cc
@@ -486,11 +487,9 @@ def _parse(stream, error_file_name):
28a3cc
         return syntax.IDLParsedSpec(spec, None)
28a3cc
 
28a3cc
 
28a3cc
-class ImportResolverBase(object):
28a3cc
+class ImportResolverBase(ABC):
28a3cc
     """Base class for resolving imported files."""
28a3cc
 
28a3cc
-    __metaclass__ = ABCMeta
28a3cc
-
28a3cc
     def __init__(self):
28a3cc
         # type: () -> None
28a3cc
         """Construct a ImportResolver."""
28a3cc
diff --git a/buildscripts/idl/idl/struct_types.py b/buildscripts/idl/idl/struct_types.py
28a3cc
index 9e2a9504ac..cd46e7c0ff 100644
28a3cc
--- a/buildscripts/idl/idl/struct_types.py
28a3cc
+++ b/buildscripts/idl/idl/struct_types.py
28a3cc
@@ -23,6 +23,7 @@ from . import ast
28a3cc
 from . import common
28a3cc
 from . import writer
28a3cc
 
28a3cc
+ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()})
28a3cc
 
28a3cc
 class ArgumentInfo(object):
28a3cc
     """Class that encapsulates information about an argument to a method."""
28a3cc
@@ -125,11 +126,9 @@ class MethodInfo(object):
28a3cc
             "${method_name}(${args});", method_name=self.method_name, args=args)
28a3cc
 
28a3cc
 
28a3cc
-class StructTypeInfoBase(object):
28a3cc
+class StructTypeInfoBase(ABC):
28a3cc
     """Base class for struct and command code generation."""
28a3cc
 
28a3cc
-    __metaclass__ = ABCMeta
28a3cc
-
28a3cc
     @abstractmethod
28a3cc
     def get_constructor_method(self):
28a3cc
         # type: () -> MethodInfo
28a3cc
diff --git a/buildscripts/idl/idl/syntax.py b/buildscripts/idl/idl/syntax.py
28a3cc
index 056d2e9dc3..ff9a3953db 100644
28a3cc
--- a/buildscripts/idl/idl/syntax.py
28a3cc
+++ b/buildscripts/idl/idl/syntax.py
28a3cc
@@ -82,7 +82,7 @@ def _item_and_type(dic):
28a3cc
     # type: (Dict[Any, List[Any]]) -> Iterator[Tuple[Any, Any]]
28a3cc
     """Return an Iterator of (key, value) pairs from a dictionary."""
28a3cc
     return itertools.chain.from_iterable((_zip_scalar(value, key)
28a3cc
-                                          for (key, value) in dic.viewitems()))
28a3cc
+                                          for (key, value) in dic.items()))
28a3cc
 
28a3cc
 
28a3cc
 class SymbolTable(object):
28a3cc
diff --git a/buildscripts/idl/tests/test_binder.py b/buildscripts/idl/tests/test_binder.py
28a3cc
index 5502b69d36..b0f4ba4269 100644
28a3cc
--- a/buildscripts/idl/tests/test_binder.py
28a3cc
+++ b/buildscripts/idl/tests/test_binder.py
28a3cc
@@ -72,7 +72,7 @@ class TestBinder(testcase.IDLTestcase):
28a3cc
             cpp_includes:
28a3cc
                 - 'bar'
28a3cc
                 - 'foo'"""))
28a3cc
-        self.assertEquals(spec.globals.cpp_namespace, "something")
28a3cc
+        self.assertEqual(spec.globals.cpp_namespace, "something")
28a3cc
         self.assertListEqual(spec.globals.cpp_includes, ['bar', 'foo'])
28a3cc
 
28a3cc
     def test_type_positive(self):
28a3cc
diff --git a/buildscripts/lint.py b/buildscripts/lint.py
28a3cc
index d4061a9b04..b1ca5b6169 100644
28a3cc
--- a/buildscripts/lint.py
28a3cc
+++ b/buildscripts/lint.py
28a3cc
@@ -2,8 +2,8 @@
28a3cc
 import sys
28a3cc
 import codecs
28a3cc
 
28a3cc
-import cpplint
28a3cc
-import utils
28a3cc
+from . import cpplint
28a3cc
+from . import utils
28a3cc
 
28a3cc
 class CheckForConfigH:
28a3cc
     def __init__(self):
28a3cc
diff --git a/buildscripts/linter/base.py b/buildscripts/linter/base.py
28a3cc
index ae78d52066..7988876c98 100644
28a3cc
--- a/buildscripts/linter/base.py
28a3cc
+++ b/buildscripts/linter/base.py
28a3cc
@@ -5,12 +5,11 @@ from __future__ import print_function
28a3cc
 from abc import ABCMeta, abstractmethod
28a3cc
 from typing import Dict, List, Optional
28a3cc
 
28a3cc
+ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()})
28a3cc
 
28a3cc
-class LinterBase(object):
28a3cc
+class LinterBase(ABC):
28a3cc
     """Base Class for all linters."""
28a3cc
 
28a3cc
-    __metaclass__ = ABCMeta
28a3cc
-
28a3cc
     def __init__(self, cmd_name, required_version):
28a3cc
         # type: (str, str) -> None
28a3cc
         """
28a3cc
diff --git a/buildscripts/linter/git.py b/buildscripts/linter/git.py
28a3cc
index edde6d0a49..4680e2f5fd 100644
28a3cc
--- a/buildscripts/linter/git.py
28a3cc
+++ b/buildscripts/linter/git.py
28a3cc
@@ -175,7 +175,7 @@ def get_files_to_check_from_patch(patches, filter_function):
28a3cc
 
28a3cc
     lines = []  # type: List[str]
28a3cc
     for patch in patches:
28a3cc
-        with open(patch, "rb") as infile:
28a3cc
+        with open(patch, "r") as infile:
28a3cc
             lines += infile.readlines()
28a3cc
 
28a3cc
     candidates = [check.match(line).group(1) for line in lines if check.match(line)]
28a3cc
diff --git a/buildscripts/linter/parallel.py b/buildscripts/linter/parallel.py
28a3cc
index 0648bfb16e..361da0c559 100644
28a3cc
--- a/buildscripts/linter/parallel.py
28a3cc
+++ b/buildscripts/linter/parallel.py
28a3cc
@@ -2,7 +2,12 @@
28a3cc
 from __future__ import absolute_import
28a3cc
 from __future__ import print_function
28a3cc
 
28a3cc
-import Queue
28a3cc
+try:
28a3cc
+  import queue
28a3cc
+except ImportError:
28a3cc
+  #Python 2
28a3cc
+  import Queue as queue
28a3cc
+
28a3cc
 import threading
28a3cc
 import time
28a3cc
 from multiprocessing import cpu_count
28a3cc
@@ -17,7 +22,7 @@ def parallel_process(items, func):
28a3cc
     except NotImplementedError:
28a3cc
         cpus = 1
28a3cc
 
28a3cc
-    task_queue = Queue.Queue()  # type: Queue.Queue
28a3cc
+    task_queue = queue.Queue()  # type: queue.Queue
28a3cc
 
28a3cc
     # Use a list so that worker function will capture this variable
28a3cc
     pp_event = threading.Event()
28a3cc
@@ -30,7 +35,7 @@ def parallel_process(items, func):
28a3cc
         while not pp_event.is_set():
28a3cc
             try:
28a3cc
                 item = task_queue.get_nowait()
28a3cc
-            except Queue.Empty:
28a3cc
+            except queue.Empty:
28a3cc
                 # if the queue is empty, exit the worker thread
28a3cc
                 pp_event.set()
28a3cc
                 return
28a3cc
diff --git a/buildscripts/resmokeconfig/loggers/__init__.py b/buildscripts/resmokeconfig/loggers/__init__.py
28a3cc
index 6511d49636..454f675ca2 100644
28a3cc
--- a/buildscripts/resmokeconfig/loggers/__init__.py
28a3cc
+++ b/buildscripts/resmokeconfig/loggers/__init__.py
28a3cc
@@ -21,7 +21,7 @@ def _get_named_loggers():
28a3cc
     named_loggers = {}
28a3cc
 
28a3cc
     try:
28a3cc
-        (root, _dirs, files) = os.walk(dirname).next()
28a3cc
+        (root, _dirs, files) = next(os.walk(dirname))
28a3cc
         for filename in files:
28a3cc
             (short_name, ext) = os.path.splitext(filename)
28a3cc
             if ext in (".yml", ".yaml"):
28a3cc
diff --git a/buildscripts/resmokeconfig/suites/__init__.py b/buildscripts/resmokeconfig/suites/__init__.py
28a3cc
index e075dd22e0..2ca2187e6e 100644
28a3cc
--- a/buildscripts/resmokeconfig/suites/__init__.py
28a3cc
+++ b/buildscripts/resmokeconfig/suites/__init__.py
28a3cc
@@ -21,7 +21,7 @@ def _get_named_suites():
28a3cc
     named_suites = {}
28a3cc
 
28a3cc
     try:
28a3cc
-        (root, _dirs, files) = os.walk(dirname).next()
28a3cc
+        (root, _dirs, files) = next(os.walk(dirname))
28a3cc
         for filename in files:
28a3cc
             (short_name, ext) = os.path.splitext(filename)
28a3cc
             if ext in (".yml", ".yaml"):
28a3cc
diff --git a/buildscripts/resmokelib/config.py b/buildscripts/resmokelib/config.py
28a3cc
index 1dcd7d7793..8a15651b4a 100644
28a3cc
--- a/buildscripts/resmokelib/config.py
28a3cc
+++ b/buildscripts/resmokelib/config.py
28a3cc
@@ -58,7 +58,7 @@ DEFAULTS = {
28a3cc
     "repeat": 1,
28a3cc
     "reportFailureStatus": "fail",
28a3cc
     "reportFile": None,
28a3cc
-    "seed": long(time.time() * 256),  # Taken from random.py code in Python 2.7.
28a3cc
+    "seed": int(time.time() * 256),  # Taken from random.py code in Python 2.7.
28a3cc
     "serviceExecutor": None,
28a3cc
     "shellReadMode": None,
28a3cc
     "shellWriteMode": None,
28a3cc
diff --git a/buildscripts/resmokelib/core/process.py b/buildscripts/resmokelib/core/process.py
28a3cc
index 03fb849616..e70f90abb4 100644
28a3cc
--- a/buildscripts/resmokelib/core/process.py
28a3cc
+++ b/buildscripts/resmokelib/core/process.py
28a3cc
@@ -196,8 +196,8 @@ class Process(object):
28a3cc
                 finally:
28a3cc
                     win32api.CloseHandle(mongo_signal_handle)
28a3cc
 
28a3cc
-                print "Failed to cleanly exit the program, calling TerminateProcess() on PID: " +\
28a3cc
-                    str(self._process.pid)
28a3cc
+                print("Failed to cleanly exit the program, calling TerminateProcess() on PID: " +\
28a3cc
+                    str(self._process.pid))
28a3cc
 
28a3cc
             # Adapted from implementation of Popen.terminate() in subprocess.py of Python 2.7
28a3cc
             # because earlier versions do not catch exceptions.
28a3cc
diff --git a/buildscripts/resmokelib/logging/buildlogger.py b/buildscripts/resmokelib/logging/buildlogger.py
28a3cc
index a577d64e3f..d5405bd15c 100644
28a3cc
--- a/buildscripts/resmokelib/logging/buildlogger.py
28a3cc
+++ b/buildscripts/resmokelib/logging/buildlogger.py
28a3cc
@@ -205,7 +205,7 @@ class BuildloggerServer(object):
28a3cc
     def __init__(self):
28a3cc
         tmp_globals = {}
28a3cc
         self.config = {}
28a3cc
-        execfile(_BUILDLOGGER_CONFIG, tmp_globals, self.config)
28a3cc
+        exec(compile(open(_BUILDLOGGER_CONFIG).read(), _BUILDLOGGER_CONFIG, 'exec'), tmp_globals, self.config)
28a3cc
 
28a3cc
         # Rename "slavename" to "username" if present.
28a3cc
         if "slavename" in self.config and "username" not in self.config:
28a3cc
diff --git a/buildscripts/resmokelib/selector.py b/buildscripts/resmokelib/selector.py
28a3cc
index 3fff181c18..4395c3b2cf 100644
28a3cc
--- a/buildscripts/resmokelib/selector.py
28a3cc
+++ b/buildscripts/resmokelib/selector.py
28a3cc
@@ -66,7 +66,7 @@ class TestFileExplorer(object):
28a3cc
             A list of paths as a list(str).
28a3cc
         """
28a3cc
         tests = []
28a3cc
-        with open(root_file_path, "rb") as filep:
28a3cc
+        with open(root_file_path, "r") as filep:
28a3cc
             for test_path in filep:
28a3cc
                 test_path = test_path.strip()
28a3cc
                 tests.append(test_path)
28a3cc
@@ -294,7 +294,7 @@ def make_expression(conf):
28a3cc
     elif isinstance(conf, dict):
28a3cc
         if len(conf) != 1:
28a3cc
             raise ValueError("Tag matching expressions should only contain one key")
28a3cc
-        key = conf.keys()[0]
28a3cc
+        key = next(iter(conf.keys()))
28a3cc
         value = conf[key]
28a3cc
         if key == "$allOf":
28a3cc
             return _AllOfExpression(_make_expression_list(value))
28a3cc
diff --git a/buildscripts/resmokelib/testing/executor.py b/buildscripts/resmokelib/testing/executor.py
28a3cc
index cc665568f0..db8d385826 100644
28a3cc
--- a/buildscripts/resmokelib/testing/executor.py
28a3cc
+++ b/buildscripts/resmokelib/testing/executor.py
28a3cc
@@ -64,7 +64,7 @@ class TestSuiteExecutor(object):
28a3cc
             jobs_to_start = num_tests
28a3cc
 
28a3cc
         # Must be done after getting buildlogger configuration.
28a3cc
-        self._jobs = [self._make_job(job_num) for job_num in xrange(jobs_to_start)]
28a3cc
+        self._jobs = [self._make_job(job_num) for job_num in range(jobs_to_start)]
28a3cc
 
28a3cc
     def run(self):
28a3cc
         """
28a3cc
@@ -290,7 +290,7 @@ class TestSuiteExecutor(object):
28a3cc
             queue.put(test_case)
28a3cc
 
28a3cc
         # Add sentinel value for each job to indicate when there are no more items to process.
28a3cc
-        for _ in xrange(len(self._jobs)):
28a3cc
+        for _ in range(len(self._jobs)):
28a3cc
             queue.put(None)
28a3cc
 
28a3cc
         return queue
28a3cc
diff --git a/buildscripts/resmokelib/testing/fixtures/interface.py b/buildscripts/resmokelib/testing/fixtures/interface.py
28a3cc
index 6dffa24e43..dfeeb1326d 100644
28a3cc
--- a/buildscripts/resmokelib/testing/fixtures/interface.py
28a3cc
+++ b/buildscripts/resmokelib/testing/fixtures/interface.py
28a3cc
@@ -4,6 +4,7 @@ Interface of the different fixtures for executing JSTests against.
28a3cc
 
28a3cc
 from __future__ import absolute_import
28a3cc
 
28a3cc
+import six
28a3cc
 import time
28a3cc
 
28a3cc
 import pymongo
28a3cc
@@ -27,13 +28,11 @@ def make_fixture(class_name, *args, **kwargs):
28a3cc
     return _FIXTURES[class_name](*args, **kwargs)
28a3cc
 
28a3cc
 
28a3cc
-class Fixture(object):
28a3cc
+class Fixture(six.with_metaclass(registry.make_registry_metaclass(_FIXTURES), object)):
28a3cc
     """
28a3cc
     Base class for all fixtures.
28a3cc
     """
28a3cc
 
28a3cc
-    __metaclass__ = registry.make_registry_metaclass(_FIXTURES)
28a3cc
-
28a3cc
     # We explicitly set the 'REGISTERED_NAME' attribute so that PyLint realizes that the attribute
28a3cc
     # is defined for all subclasses of Fixture.
28a3cc
     REGISTERED_NAME = "Fixture"
28a3cc
diff --git a/buildscripts/resmokelib/testing/fixtures/replicaset.py b/buildscripts/resmokelib/testing/fixtures/replicaset.py
28a3cc
index 025ce257a7..678ef45930 100644
28a3cc
--- a/buildscripts/resmokelib/testing/fixtures/replicaset.py
28a3cc
+++ b/buildscripts/resmokelib/testing/fixtures/replicaset.py
28a3cc
@@ -75,7 +75,7 @@ class ReplicaSetFixture(interface.ReplFixture):
28a3cc
         self.replset_name = self.mongod_options.get("replSet", "rs")
28a3cc
 
28a3cc
         if not self.nodes:
28a3cc
-            for i in xrange(self.num_nodes):
28a3cc
+            for i in range(self.num_nodes):
28a3cc
                 node = self._new_mongod(i, self.replset_name)
28a3cc
                 self.nodes.append(node)
28a3cc
 
28a3cc
diff --git a/buildscripts/resmokelib/testing/fixtures/shardedcluster.py b/buildscripts/resmokelib/testing/fixtures/shardedcluster.py
28a3cc
index 4f90d16f51..eb96b8be38 100644
28a3cc
--- a/buildscripts/resmokelib/testing/fixtures/shardedcluster.py
28a3cc
+++ b/buildscripts/resmokelib/testing/fixtures/shardedcluster.py
28a3cc
@@ -85,7 +85,7 @@ class ShardedClusterFixture(interface.Fixture):
28a3cc
             self.configsvr.setup()
28a3cc
 
28a3cc
         if not self.shards:
28a3cc
-            for i in xrange(self.num_shards):
28a3cc
+            for i in range(self.num_shards):
28a3cc
                 if self.num_rs_nodes_per_shard is None:
28a3cc
                     shard = self._new_standalone_shard(i)
28a3cc
                 elif isinstance(self.num_rs_nodes_per_shard, int):
28a3cc
diff --git a/buildscripts/resmokelib/testing/hooks/interface.py b/buildscripts/resmokelib/testing/hooks/interface.py
28a3cc
index 6ca4ae79a7..a225a1b8e9 100644
28a3cc
--- a/buildscripts/resmokelib/testing/hooks/interface.py
28a3cc
+++ b/buildscripts/resmokelib/testing/hooks/interface.py
28a3cc
@@ -7,6 +7,7 @@ from __future__ import absolute_import
28a3cc
 from ... import logging
28a3cc
 from ...utils import registry
28a3cc
 
28a3cc
+import six
28a3cc
 
28a3cc
 _HOOKS = {}
28a3cc
 
28a3cc
@@ -22,13 +23,11 @@ def make_custom_behavior(class_name, *args, **kwargs):
28a3cc
     return _HOOKS[class_name](*args, **kwargs)
28a3cc
 
28a3cc
 
28a3cc
-class CustomBehavior(object):
28a3cc
+class CustomBehavior(six.with_metaclass(registry.make_registry_metaclass(_HOOKS), object)):
28a3cc
     """
28a3cc
     The common interface all CustomBehaviors will inherit from.
28a3cc
     """
28a3cc
 
28a3cc
-    __metaclass__ = registry.make_registry_metaclass(_HOOKS)
28a3cc
-
28a3cc
     REGISTERED_NAME = registry.LEAVE_UNREGISTERED
28a3cc
 
28a3cc
     @staticmethod
28a3cc
diff --git a/buildscripts/resmokelib/testing/suite.py b/buildscripts/resmokelib/testing/suite.py
28a3cc
index 132a2d70d9..07262d194a 100644
28a3cc
--- a/buildscripts/resmokelib/testing/suite.py
28a3cc
+++ b/buildscripts/resmokelib/testing/suite.py
28a3cc
@@ -262,7 +262,7 @@ class Suite(object):
28a3cc
         sb.append("Executed %d times in %0.2f seconds:" % (num_iterations, total_time_taken))
28a3cc
 
28a3cc
         combined_summary = _summary.Summary(0, 0.0, 0, 0, 0, 0)
28a3cc
-        for iteration in xrange(num_iterations):
28a3cc
+        for iteration in range(num_iterations):
28a3cc
             # Summarize each execution as a bulleted list of results.
28a3cc
             bulleter_sb = []
28a3cc
             summary = self._summarize_report(
28a3cc
diff --git a/buildscripts/resmokelib/testing/summary.py b/buildscripts/resmokelib/testing/summary.py
28a3cc
index bb44472caa..54da2181d5 100644
28a3cc
--- a/buildscripts/resmokelib/testing/summary.py
28a3cc
+++ b/buildscripts/resmokelib/testing/summary.py
28a3cc
@@ -17,6 +17,6 @@ def combine(summary1, summary2):
28a3cc
     Returns a summary representing the sum of 'summary1' and 'summary2'.
28a3cc
     """
28a3cc
     args = []
28a3cc
-    for i in xrange(len(Summary._fields)):
28a3cc
+    for i in range(len(Summary._fields)):
28a3cc
         args.append(summary1[i] + summary2[i])
28a3cc
     return Summary._make(args)
28a3cc
diff --git a/buildscripts/resmokelib/testing/testcases/interface.py b/buildscripts/resmokelib/testing/testcases/interface.py
28a3cc
index be7f14afd5..f736bd5c36 100644
28a3cc
--- a/buildscripts/resmokelib/testing/testcases/interface.py
28a3cc
+++ b/buildscripts/resmokelib/testing/testcases/interface.py
28a3cc
@@ -7,6 +7,7 @@ from __future__ import absolute_import
28a3cc
 
28a3cc
 import os
28a3cc
 import os.path
28a3cc
+import six
28a3cc
 import unittest
28a3cc
 
28a3cc
 from ... import config
28a3cc
@@ -27,13 +28,11 @@ def make_test_case(test_kind, *args, **kwargs):
28a3cc
     return _TEST_CASES[test_kind](*args, **kwargs)
28a3cc
 
28a3cc
 
28a3cc
-class TestCase(unittest.TestCase):
28a3cc
+class TestCase(six.with_metaclass(registry.make_registry_metaclass(_TEST_CASES), unittest.TestCase)):
28a3cc
     """
28a3cc
     A test case to execute.
28a3cc
     """
28a3cc
 
28a3cc
-    __metaclass__ = registry.make_registry_metaclass(_TEST_CASES)
28a3cc
-
28a3cc
     REGISTERED_NAME = registry.LEAVE_UNREGISTERED
28a3cc
 
28a3cc
     def __init__(self, logger, test_kind, test_name):
28a3cc
@@ -46,10 +45,10 @@ class TestCase(unittest.TestCase):
28a3cc
         if not isinstance(logger, logging.Logger):
28a3cc
             raise TypeError("logger must be a Logger instance")
28a3cc
 
28a3cc
-        if not isinstance(test_kind, basestring):
28a3cc
+        if not isinstance(test_kind, str):
28a3cc
             raise TypeError("test_kind must be a string")
28a3cc
 
28a3cc
-        if not isinstance(test_name, basestring):
28a3cc
+        if not isinstance(test_name, str):
28a3cc
             raise TypeError("test_name must be a string")
28a3cc
 
28a3cc
         # When the TestCase is created by the TestSuiteExecutor (through a call to make_test_case())
28a3cc
diff --git a/buildscripts/resmokelib/testing/testcases/jstest.py b/buildscripts/resmokelib/testing/testcases/jstest.py
28a3cc
index adb28285f0..528a9747a9 100644
28a3cc
--- a/buildscripts/resmokelib/testing/testcases/jstest.py
28a3cc
+++ b/buildscripts/resmokelib/testing/testcases/jstest.py
28a3cc
@@ -235,7 +235,7 @@ class JSTestCase(interface.TestCase):
28a3cc
         test_cases = []
28a3cc
         try:
28a3cc
             # If there are multiple clients, make a new thread for each client.
28a3cc
-            for thread_id in xrange(self.num_clients):
28a3cc
+            for thread_id in range(self.num_clients):
28a3cc
                 logger = self.logger.new_test_thread_logger(self.test_kind, str(thread_id))
28a3cc
                 test_case = self._create_test_case_for_thread(logger, thread_id)
28a3cc
                 test_cases.append(test_case)
28a3cc
diff --git a/buildscripts/resmokelib/utils/__init__.py b/buildscripts/resmokelib/utils/__init__.py
28a3cc
index fa782f3430..3ce73c9b64 100644
28a3cc
--- a/buildscripts/resmokelib/utils/__init__.py
28a3cc
+++ b/buildscripts/resmokelib/utils/__init__.py
28a3cc
@@ -43,14 +43,14 @@ def is_string_list(lst):
28a3cc
     """
28a3cc
     Returns true if 'lst' is a list of strings, and false otherwise.
28a3cc
     """
28a3cc
-    return isinstance(lst, list) and all(isinstance(x, basestring) for x in lst)
28a3cc
+    return isinstance(lst, list) and all(isinstance(x, str) for x in lst)
28a3cc
 
28a3cc
 
28a3cc
 def is_string_set(value):
28a3cc
     """
28a3cc
     Returns true if 'value' is a set of strings, and false otherwise.
28a3cc
     """
28a3cc
-    return isinstance(value, set) and all(isinstance(x, basestring) for x in value)
28a3cc
+    return isinstance(value, set) and all(isinstance(x, str) for x in value)
28a3cc
 
28a3cc
 
28a3cc
 def is_js_file(filename):
28a3cc
diff --git a/buildscripts/resmokelib/utils/globstar.py b/buildscripts/resmokelib/utils/globstar.py
28a3cc
index 644ebfe3e3..52100d7d9d 100644
28a3cc
--- a/buildscripts/resmokelib/utils/globstar.py
28a3cc
+++ b/buildscripts/resmokelib/utils/globstar.py
28a3cc
@@ -145,7 +145,7 @@ def _list_dir(pathname):
28a3cc
     """
28a3cc
 
28a3cc
     try:
28a3cc
-        (_root, dirs, files) = os.walk(pathname).next()
28a3cc
+        (_root, dirs, files) = next(os.walk(pathname))
28a3cc
         return (dirs, files)
28a3cc
     except StopIteration:
28a3cc
         return None  # 'pathname' directory does not exist
28a3cc
diff --git a/buildscripts/resmokelib/utils/jscomment.py b/buildscripts/resmokelib/utils/jscomment.py
28a3cc
index 18da788582..a393c43723 100644
28a3cc
--- a/buildscripts/resmokelib/utils/jscomment.py
28a3cc
+++ b/buildscripts/resmokelib/utils/jscomment.py
28a3cc
@@ -39,7 +39,7 @@ def get_tags(pathname):
28a3cc
                 # TODO: it might be worth supporting the block (indented) style of YAML lists in
28a3cc
                 #       addition to the flow (bracketed) style
28a3cc
                 tags = yaml.safe_load(_strip_jscomments(match.group(1)))
28a3cc
-                if not isinstance(tags, list) and all(isinstance(tag, basestring) for tag in tags):
28a3cc
+                if not isinstance(tags, list) and all(isinstance(tag, str) for tag in tags):
28a3cc
                     raise TypeError("Expected a list of string tags, but got '%s'" % (tags))
28a3cc
                 return tags
28a3cc
             except yaml.YAMLError as err:
28a3cc
diff --git a/buildscripts/resmokelib/utils/queue.py b/buildscripts/resmokelib/utils/queue.py
28a3cc
index 80da5e2cc6..41d23d54bf 100644
28a3cc
--- a/buildscripts/resmokelib/utils/queue.py
28a3cc
+++ b/buildscripts/resmokelib/utils/queue.py
28a3cc
@@ -9,15 +9,20 @@ See https://bugs.python.org/issue1167930 for more details.
28a3cc
 
28a3cc
 from __future__ import absolute_import
28a3cc
 
28a3cc
-import Queue
28a3cc
+try:
28a3cc
+  import queue
28a3cc
+except ImportError:
28a3cc
+  #Python 2
28a3cc
+  import Queue as queue
28a3cc
+
28a3cc
 import time
28a3cc
 
28a3cc
 
28a3cc
 # Exception that is raised when get_nowait() is called on an empty Queue.
28a3cc
-Empty = Queue.Empty
28a3cc
+Empty = queue.Empty
28a3cc
 
28a3cc
 
28a3cc
-class Queue(Queue.Queue):
28a3cc
+class Queue(queue.Queue):
28a3cc
     """
28a3cc
     A multi-producer, multi-consumer queue.
28a3cc
     """
28a3cc
diff --git a/buildscripts/utils.py b/buildscripts/utils.py
28a3cc
index 69a78921ca..93c697adca 100644
28a3cc
--- a/buildscripts/utils.py
28a3cc
+++ b/buildscripts/utils.py
28a3cc
@@ -122,7 +122,7 @@ def getprocesslist():
28a3cc
     raw = ""
28a3cc
     try:
28a3cc
         raw = execsys( "/bin/ps axww" )[0]
28a3cc
-    except Exception,e:
28a3cc
+    except Exception as e:
28a3cc
         print( "can't get processlist: " + str( e ) )
28a3cc
 
28a3cc
     r = re.compile( "[\r\n]+" )
28a3cc
@@ -145,7 +145,7 @@ def choosePathExist( choices , default=None):
28a3cc
     return default
28a3cc
 
28a3cc
 def filterExists(paths):
28a3cc
-    return filter(os.path.exists, paths)
28a3cc
+    return list(filter(os.path.exists, paths))
28a3cc
 
28a3cc
 def ensureDir( name ):
28a3cc
     d = os.path.dirname( name )
28a3cc
@@ -176,7 +176,7 @@ def didMongodStart( port=27017 , timeout=20 ):
28a3cc
         try:
28a3cc
             checkMongoPort( port )
28a3cc
             return True
28a3cc
-        except Exception,e:
28a3cc
+        except Exception as e:
28a3cc
             print( e )
28a3cc
             timeout = timeout - 1
28a3cc
     return False
28a3cc
@@ -213,7 +213,7 @@ def find_python(min_version=(2, 5)):
28a3cc
         pass
28a3cc
 
28a3cc
     version = re.compile(r'[Pp]ython ([\d\.]+)', re.MULTILINE)
28a3cc
-    binaries = ('python27', 'python2.7', 'python26', 'python2.6', 'python25', 'python2.5', 'python')
28a3cc
+    binaries = ('python3', 'python27', 'python2.7', 'python26', 'python2.6', 'python25', 'python2.5', 'python')
28a3cc
     for binary in binaries:
28a3cc
         try:
28a3cc
             out, err = subprocess.Popen([binary, '-V'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
28a3cc
@@ -251,7 +251,7 @@ def run_smoke_command(*args):
28a3cc
 # at the position they occurred
28a3cc
 def replace_with_repr(unicode_error):
28a3cc
     offender = unicode_error.object[unicode_error.start:unicode_error.end]
28a3cc
-    return (unicode(repr(offender).strip("'").strip('"')), unicode_error.end)
28a3cc
+    return (str(repr(offender).strip("'").strip('"')), unicode_error.end)
28a3cc
 
28a3cc
 codecs.register_error('repr', replace_with_repr)
28a3cc
 
28a3cc
diff --git a/site_scons/libdeps.py b/site_scons/libdeps.py
28a3cc
index 632ed29be5..1641c3ba90 100644
28a3cc
--- a/site_scons/libdeps.py
28a3cc
+++ b/site_scons/libdeps.py
28a3cc
@@ -122,7 +122,7 @@ def __get_libdeps(node):
28a3cc
                 marked.add(n.target_node)
28a3cc
                 tsorted.append(n.target_node)
28a3cc
 
28a3cc
-            except DependencyCycleError, e:
28a3cc
+            except DependencyCycleError as e:
28a3cc
                 if len(e.cycle_nodes) == 1 or e.cycle_nodes[0] != e.cycle_nodes[-1]:
28a3cc
                     e.cycle_nodes.insert(0, n.target_node)
28a3cc
                 raise
28a3cc
@@ -150,7 +150,7 @@ def __get_syslibdeps(node):
28a3cc
         for lib in __get_libdeps(node):
28a3cc
             for syslib in node.get_env().Flatten(lib.get_env().get(syslibdeps_env_var, [])):
28a3cc
                 if syslib:
28a3cc
-                    if type(syslib) in (str, unicode) and syslib.startswith(missing_syslibdep):
28a3cc
+                    if type(syslib) in (str, str) and syslib.startswith(missing_syslibdep):
28a3cc
                         print("Target '%s' depends on the availability of a "
28a3cc
                               "system provided library for '%s', "
28a3cc
                               "but no suitable library was found during configuration." %
28a3cc
@@ -209,7 +209,7 @@ def get_syslibdeps(source, target, env, for_signature):
28a3cc
         # they're believed to represent library short names, that should be prefixed with -l
28a3cc
         # or the compiler-specific equivalent.  I.e., 'm' becomes '-lm', but 'File("m.a") is passed
28a3cc
         # through whole cloth.
28a3cc
-        if type(d) in (str, unicode):
28a3cc
+        if type(d) in (str, str):
28a3cc
             result.append('%s%s%s' % (lib_link_prefix, d, lib_link_suffix))
28a3cc
         else:
28a3cc
             result.append(d)
28a3cc
diff --git a/site_scons/mongo/__init__.py b/site_scons/mongo/__init__.py
28a3cc
index 510bd7bcc2..f77478092b 100644
28a3cc
--- a/site_scons/mongo/__init__.py
28a3cc
+++ b/site_scons/mongo/__init__.py
28a3cc
@@ -5,4 +5,4 @@
28a3cc
 def print_build_failures():
28a3cc
     from SCons.Script import GetBuildFailures
28a3cc
     for bf in GetBuildFailures():
28a3cc
-        print "%s failed: %s" % (bf.node, bf.errstr)
28a3cc
+        print("%s failed: %s" % (bf.node, bf.errstr))
28a3cc
diff --git a/site_scons/mongo/generators.py b/site_scons/mongo/generators.py
28a3cc
index c07e86a4d1..5958e6923b 100644
28a3cc
--- a/site_scons/mongo/generators.py
28a3cc
+++ b/site_scons/mongo/generators.py
28a3cc
@@ -1,6 +1,6 @@
28a3cc
 # -*- mode: python; -*-
28a3cc
 
28a3cc
-import md5
28a3cc
+import hashlib
28a3cc
 
28a3cc
 # Default and alternative generator definitions go here.
28a3cc
 
28a3cc
@@ -44,7 +44,7 @@ def default_variant_dir_generator(target, source, env, for_signature):
28a3cc
 
28a3cc
     # Hash the named options and their values, and take the first 8 characters of the hash as
28a3cc
     # the variant name
28a3cc
-    hasher = md5.md5()
28a3cc
+    hasher = hashlib.md5()
28a3cc
     for option in variant_options:
28a3cc
         hasher.update(option)
28a3cc
         hasher.update(str(env.GetOption(option)))
28a3cc
diff --git a/site_scons/site_tools/dagger/__init__.py b/site_scons/site_tools/dagger/__init__.py
28a3cc
index f05228cfe4..f10b4027e1 100644
28a3cc
--- a/site_scons/site_tools/dagger/__init__.py
28a3cc
+++ b/site_scons/site_tools/dagger/__init__.py
28a3cc
@@ -5,7 +5,7 @@ import logging
28a3cc
 
28a3cc
 import SCons
28a3cc
 
28a3cc
-import dagger
28a3cc
+from . import dagger
28a3cc
 
28a3cc
 def generate(env, **kwargs):
28a3cc
     """The entry point for our tool. However, the builder for
28a3cc
diff --git a/site_scons/site_tools/dagger/dagger.py b/site_scons/site_tools/dagger/dagger.py
28a3cc
index 1eeefe1ea3..03e7603d29 100644
28a3cc
--- a/site_scons/site_tools/dagger/dagger.py
28a3cc
+++ b/site_scons/site_tools/dagger/dagger.py
28a3cc
@@ -40,8 +40,8 @@ import sys
28a3cc
 
28a3cc
 import SCons
28a3cc
 
28a3cc
-import graph
28a3cc
-import graph_consts
28a3cc
+from . import graph
28a3cc
+from . import graph_consts
28a3cc
 
28a3cc
 
28a3cc
 LIB_DB = [] # Stores every SCons library nodes
28a3cc
@@ -269,7 +269,7 @@ def write_obj_db(target, source, env):
28a3cc
     for obj in OBJ_DB:
28a3cc
         __generate_file_rels(obj, g)
28a3cc
 
28a3cc
-    for exe in EXE_DB.keys():
28a3cc
+    for exe in list(EXE_DB.keys()):
28a3cc
         __generate_exe_rels(exe, g)
28a3cc
 
28a3cc
     # target is given as a list of target SCons nodes - this builder is only responsible for
28a3cc
diff --git a/site_scons/site_tools/dagger/graph.py b/site_scons/site_tools/dagger/graph.py
28a3cc
index 5ebe6f4506..379d5245e6 100644
28a3cc
--- a/site_scons/site_tools/dagger/graph.py
28a3cc
+++ b/site_scons/site_tools/dagger/graph.py
28a3cc
@@ -4,11 +4,13 @@ import abc
28a3cc
 import json
28a3cc
 import copy
28a3cc
 
28a3cc
-import graph_consts
28a3cc
+from . import graph_consts
28a3cc
 
28a3cc
 if sys.version_info >= (3, 0):
28a3cc
     basestring = str
28a3cc
 
28a3cc
+ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()})
28a3cc
+
28a3cc
 class Graph(object):
28a3cc
     """Graph class for storing the build dependency graph. The graph stores the
28a3cc
     directed edges as a nested dict of { RelationshipType: {From_Node: Set of
28a3cc
@@ -141,7 +143,7 @@ class Graph(object):
28a3cc
             node_dict["id"] = id
28a3cc
             node_dict["node"] = {}
28a3cc
 
28a3cc
-            for property, value in vars(node).iteritems():
28a3cc
+            for property, value in vars(node).items():
28a3cc
                 if isinstance(value, set):
28a3cc
                     node_dict["node"][property] = list(value)
28a3cc
                 else:
28a3cc
@@ -170,10 +172,9 @@ class Graph(object):
28a3cc
                 sum(len(x) for x in self._edges.values()), hash(self))
28a3cc
 
28a3cc
 
28a3cc
-class NodeInterface(object):
28a3cc
+class NodeInterface(ABC):
28a3cc
     """Abstract base class for all Node Objects - All nodes must have an id and name
28a3cc
     """
28a3cc
-    __metaclass__ = abc.ABCMeta
28a3cc
 
28a3cc
     @abc.abstractproperty
28a3cc
     def id(self):
28a3cc
@@ -190,7 +191,7 @@ class NodeLib(NodeInterface):
28a3cc
     def __init__(self, id, name, input=None):
28a3cc
         if isinstance(input, dict):
28a3cc
             should_fail = False
28a3cc
-            for k, v in input.iteritems():
28a3cc
+            for k, v in input.items():
28a3cc
                 try:
28a3cc
                     if isinstance(v, list):
28a3cc
                         setattr(self, k, set(v))
28a3cc
@@ -310,7 +311,7 @@ class NodeSymbol(NodeInterface):
28a3cc
         if isinstance(input, dict):
28a3cc
             should_fail = False
28a3cc
 
28a3cc
-            for k, v in input.iteritems():
28a3cc
+            for k, v in input.items():
28a3cc
                 try:
28a3cc
                     if isinstance(v, list):
28a3cc
                         setattr(self, k, set(v))
28a3cc
@@ -435,7 +436,7 @@ class NodeFile(NodeInterface):
28a3cc
     def __init__(self, id, name, input=None):
28a3cc
         if isinstance(input, dict):
28a3cc
             should_fail = False
28a3cc
-            for k, v in input.iteritems():
28a3cc
+            for k, v in input.items():
28a3cc
                 try:
28a3cc
                     if isinstance(v, list):
28a3cc
                         setattr(self, k, set(v))
28a3cc
@@ -551,7 +552,7 @@ class NodeExe(NodeInterface):
28a3cc
     def __init__(self, id, name, input=None):
28a3cc
         if isinstance(input, dict):
28a3cc
             should_fail = False
28a3cc
-            for k, v in input.iteritems():
28a3cc
+            for k, v in input.items():
28a3cc
                 try:
28a3cc
                     if isinstance(v, list):
28a3cc
                         setattr(self, k, set(v))
28a3cc
diff --git a/site_scons/site_tools/dagger/graph_consts.py b/site_scons/site_tools/dagger/graph_consts.py
28a3cc
index 81fe86d75c..a922a4f3f6 100644
28a3cc
--- a/site_scons/site_tools/dagger/graph_consts.py
28a3cc
+++ b/site_scons/site_tools/dagger/graph_consts.py
28a3cc
@@ -17,8 +17,8 @@ NODE_SYM = 2
28a3cc
 NODE_FILE = 3
28a3cc
 NODE_EXE = 4
28a3cc
 
28a3cc
-RELATIONSHIP_TYPES = range(1, 9)
28a3cc
-NODE_TYPES = range(1, 5)
28a3cc
+RELATIONSHIP_TYPES = list(range(1, 9))
28a3cc
+NODE_TYPES = list(range(1, 5))
28a3cc
 
28a3cc
 
28a3cc
 """Error/query codes"""
28a3cc
diff --git a/site_scons/site_tools/dagger/graph_test.py b/site_scons/site_tools/dagger/graph_test.py
28a3cc
index bc84f5868c..6c0168cf97 100644
28a3cc
--- a/site_scons/site_tools/dagger/graph_test.py
28a3cc
+++ b/site_scons/site_tools/dagger/graph_test.py
28a3cc
@@ -5,8 +5,8 @@ from JSON
28a3cc
 
28a3cc
 import json
28a3cc
 import unittest
28a3cc
-import graph
28a3cc
-import graph_consts
28a3cc
+from . import graph
28a3cc
+from . import graph_consts
28a3cc
 
28a3cc
 
28a3cc
 def generate_graph():
28a3cc
@@ -122,15 +122,15 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions):
28a3cc
         node = graph.NodeLib("test_node", "test_node")
28a3cc
         self.g._nodes = {"test_node": node}
28a3cc
 
28a3cc
-        self.assertEquals(self.g.get_node("test_node"), node)
28a3cc
+        self.assertEqual(self.g.get_node("test_node"), node)
28a3cc
 
28a3cc
-        self.assertEquals(self.g.get_node("missing_node"), None)
28a3cc
+        self.assertEqual(self.g.get_node("missing_node"), None)
28a3cc
 
28a3cc
     def test_add_node(self):
28a3cc
         node = graph.NodeLib("test_node", "test_node")
28a3cc
         self.g.add_node(node)
28a3cc
 
28a3cc
-        self.assertEquals(self.g.get_node("test_node"), node)
28a3cc
+        self.assertEqual(self.g.get_node("test_node"), node)
28a3cc
 
28a3cc
         self.assertRaises(ValueError, self.g.add_node, node)
28a3cc
 
28a3cc
@@ -153,16 +153,16 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions):
28a3cc
         self.g.add_edge(graph_consts.LIB_FIL, self.from_node_lib.id,
28a3cc
                         self.to_node_file.id)
28a3cc
 
28a3cc
-        self.assertEquals(self.g.edges[graph_consts.LIB_LIB][
28a3cc
+        self.assertEqual(self.g.edges[graph_consts.LIB_LIB][
28a3cc
             self.from_node_lib.id], set([self.to_node_lib.id]))
28a3cc
 
28a3cc
-        self.assertEquals(self.g.edges[graph_consts.LIB_SYM][
28a3cc
+        self.assertEqual(self.g.edges[graph_consts.LIB_SYM][
28a3cc
             self.from_node_lib.id], set([self.to_node_sym.id]))
28a3cc
 
28a3cc
-        self.assertEquals(self.g.edges[graph_consts.LIB_FIL][
28a3cc
+        self.assertEqual(self.g.edges[graph_consts.LIB_FIL][
28a3cc
             self.from_node_lib.id], set([self.to_node_file.id]))
28a3cc
 
28a3cc
-        self.assertEquals(self.to_node_lib.dependent_libs,
28a3cc
+        self.assertEqual(self.to_node_lib.dependent_libs,
28a3cc
                           set([self.from_node_lib.id]))
28a3cc
 
28a3cc
     def test_add_edge_files(self):
28a3cc
@@ -173,14 +173,14 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions):
28a3cc
         self.g.add_edge(graph_consts.FIL_LIB, self.from_node_file.id,
28a3cc
                         self.to_node_lib.id)
28a3cc
 
28a3cc
-        self.assertEquals(self.g.edges[graph_consts.FIL_FIL][
28a3cc
+        self.assertEqual(self.g.edges[graph_consts.FIL_FIL][
28a3cc
             self.from_node_file.id], set([self.to_node_file.id]))
28a3cc
-        self.assertEquals(self.g.edges[graph_consts.FIL_SYM][
28a3cc
+        self.assertEqual(self.g.edges[graph_consts.FIL_SYM][
28a3cc
             self.from_node_file.id], set([self.to_node_sym.id]))
28a3cc
-        self.assertEquals(self.g.edges[graph_consts.FIL_LIB][
28a3cc
+        self.assertEqual(self.g.edges[graph_consts.FIL_LIB][
28a3cc
             self.from_node_file.id], set([self.to_node_lib.id]))
28a3cc
 
28a3cc
-        self.assertEquals(self.to_node_file.dependent_files,
28a3cc
+        self.assertEqual(self.to_node_file.dependent_files,
28a3cc
                           set([self.from_node_file.id]))
28a3cc
 
28a3cc
     def test_export_to_json(self):
28a3cc
@@ -188,7 +188,7 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions):
28a3cc
         generated_graph.export_to_json("export_test.json")
28a3cc
         generated = open("export_test.json", "r")
28a3cc
         correct = open("test_graph.json", "r")
28a3cc
-        self.assertEquals(json.load(generated), json.load(correct))
28a3cc
+        self.assertEqual(json.load(generated), json.load(correct))
28a3cc
         generated.close()
28a3cc
         correct.close()
28a3cc
 
28a3cc
@@ -205,7 +205,7 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions):
28a3cc
             self.assertNodeEquals(
28a3cc
                 graph_fromJSON.get_node(id), correct_graph.get_node(id))
28a3cc
 
28a3cc
-        self.assertEquals(graph_fromJSON.edges, correct_graph.edges)
28a3cc
+        self.assertEqual(graph_fromJSON.edges, correct_graph.edges)
28a3cc
 
28a3cc
 
28a3cc
 if __name__ == '__main__':
28a3cc
diff --git a/site_scons/site_tools/distsrc.py b/site_scons/site_tools/distsrc.py
28a3cc
index 861f5d9e2e..d2dff0b612 100644
28a3cc
--- a/site_scons/site_tools/distsrc.py
28a3cc
+++ b/site_scons/site_tools/distsrc.py
28a3cc
@@ -20,7 +20,7 @@ import shutil
28a3cc
 import tarfile
28a3cc
 import time
28a3cc
 import zipfile
28a3cc
-import StringIO
28a3cc
+import io
28a3cc
 
28a3cc
 from distutils.spawn import find_executable
28a3cc
 
28a3cc
@@ -82,7 +82,7 @@ class DistSrcTarArchive(DistSrcArchive):
28a3cc
 
28a3cc
     def append_file_contents(self, filename, file_contents,
28a3cc
             mtime=time.time(),
28a3cc
-            mode=0644,
28a3cc
+            mode=0o644,
28a3cc
             uname="root",
28a3cc
             gname="root"):
28a3cc
         file_metadata = tarfile.TarInfo(name=filename)
28a3cc
@@ -91,7 +91,7 @@ class DistSrcTarArchive(DistSrcArchive):
28a3cc
         file_metadata.uname = uname
28a3cc
         file_metadata.gname = gname
28a3cc
         file_metadata.size = len(file_contents)
28a3cc
-        file_buf = StringIO.StringIO(file_contents)
28a3cc
+        file_buf = io.StringIO(file_contents)
28a3cc
         if self.archive_mode == 'r':
28a3cc
             self.archive_file.close()
28a3cc
             self.archive_file = tarfile.open(
28a3cc
@@ -119,7 +119,7 @@ class DistSrcZipArchive(DistSrcArchive):
28a3cc
             name=key,
28a3cc
             size=item_data.file_size,
28a3cc
             mtime=time.mktime(fixed_time),
28a3cc
-            mode=0775 if is_dir else 0664,
28a3cc
+            mode=0o775 if is_dir else 0o664,
28a3cc
             type=tarfile.DIRTYPE if is_dir else tarfile.REGTYPE,
28a3cc
             uid=0,
28a3cc
             gid=0,
28a3cc
@@ -129,7 +129,7 @@ class DistSrcZipArchive(DistSrcArchive):
28a3cc
 
28a3cc
     def append_file_contents(self, filename, file_contents,
28a3cc
             mtime=time.time(),
28a3cc
-            mode=0644,
28a3cc
+            mode=0o644,
28a3cc
             uname="root",
28a3cc
             gname="root"):
28a3cc
         self.archive_file.writestr(filename, file_contents)
28a3cc
@@ -139,7 +139,7 @@ class DistSrcZipArchive(DistSrcArchive):
28a3cc
 
28a3cc
 def build_error_action(msg):
28a3cc
     def error_stub(target=None, source=None, env=None):
28a3cc
-        print msg
28a3cc
+        print(msg)
28a3cc
         env.Exit(1)
28a3cc
     return [ error_stub ]
28a3cc
 
28a3cc
@@ -162,7 +162,7 @@ def distsrc_action_generator(source, target, env, for_signature):
28a3cc
 
28a3cc
     target_ext = str(target[0])[-3:]
28a3cc
     if not target_ext in [ 'zip', 'tar' ]:
28a3cc
-        print "Invalid file format for distsrc. Must be tar or zip file"
28a3cc
+        print("Invalid file format for distsrc. Must be tar or zip file")
28a3cc
         env.Exit(1)
28a3cc
 
28a3cc
     git_cmd = "\"%s\" archive --format %s --output %s --prefix ${MONGO_DIST_SRC_PREFIX} HEAD" % (
28a3cc
diff --git a/site_scons/site_tools/icecream.py b/site_scons/site_tools/icecream.py
28a3cc
index 9838b63349..fdf0c26030 100644
28a3cc
--- a/site_scons/site_tools/icecream.py
28a3cc
+++ b/site_scons/site_tools/icecream.py
28a3cc
@@ -99,7 +99,7 @@ def generate(env):
28a3cc
     suffixes = _CSuffixes + _CXXSuffixes
28a3cc
     for object_builder in SCons.Tool.createObjBuilders(env):
28a3cc
         emitterdict = object_builder.builder.emitter
28a3cc
-        for suffix in emitterdict.iterkeys():
28a3cc
+        for suffix in emitterdict.keys():
28a3cc
             if not suffix in suffixes:
28a3cc
                 continue
28a3cc
             base = emitterdict[suffix]
28a3cc
diff --git a/site_scons/site_tools/idl_tool.py b/site_scons/site_tools/idl_tool.py
28a3cc
index 78bedfaa74..628f345361 100755
28a3cc
--- a/site_scons/site_tools/idl_tool.py
28a3cc
+++ b/site_scons/site_tools/idl_tool.py
28a3cc
@@ -47,7 +47,7 @@ def idl_scanner(node, env, path):
28a3cc
 
28a3cc
     deps_list = deps_str.splitlines()
28a3cc
 
28a3cc
-    nodes_deps_list = [ env.File(d) for d in deps_list]
28a3cc
+    nodes_deps_list = [ env.File(d.decode("utf-8")) for d in deps_list]
28a3cc
     nodes_deps_list.extend(env.Glob('#buildscripts/idl/*.py'))
28a3cc
     nodes_deps_list.extend(env.Glob('#buildscripts/idl/idl/*.py'))
28a3cc
 
28a3cc
diff --git a/site_scons/site_tools/jstoh.py b/site_scons/site_tools/jstoh.py
28a3cc
index dc90b324b2..567958a50f 100644
28a3cc
--- a/site_scons/site_tools/jstoh.py
28a3cc
+++ b/site_scons/site_tools/jstoh.py
28a3cc
@@ -1,3 +1,5 @@
28a3cc
+from __future__ import unicode_literals
28a3cc
+
28a3cc
 import os
28a3cc
 import sys
28a3cc
 
28a3cc
@@ -39,8 +41,8 @@ def jsToHeader(target, source):
28a3cc
 
28a3cc
     text = '\n'.join(h)
28a3cc
 
28a3cc
-    print "writing: %s" % outFile
28a3cc
-    with open(outFile, 'wb') as out:
28a3cc
+    print("writing: %s" % outFile)
28a3cc
+    with open(outFile, 'w') as out:
28a3cc
         try:
28a3cc
             out.write(text)
28a3cc
         finally:
28a3cc
@@ -49,7 +51,7 @@ def jsToHeader(target, source):
28a3cc
 
28a3cc
 if __name__ == "__main__":
28a3cc
     if len(sys.argv) < 3:
28a3cc
-        print "Must specify [target] [source] "
28a3cc
+        print("Must specify [target] [source] ")
28a3cc
         sys.exit(1)
28a3cc
 
28a3cc
     jsToHeader(sys.argv[1], sys.argv[2:])
28a3cc
diff --git a/site_scons/site_tools/mongo_integrationtest.py b/site_scons/site_tools/mongo_integrationtest.py
28a3cc
index ff9a5f451b..fccbbebb47 100644
28a3cc
--- a/site_scons/site_tools/mongo_integrationtest.py
28a3cc
+++ b/site_scons/site_tools/mongo_integrationtest.py
28a3cc
@@ -12,10 +12,10 @@ def register_integration_test(env, test):
28a3cc
     env.Alias('$INTEGRATION_TEST_ALIAS', installed_test)
28a3cc
 
28a3cc
 def integration_test_list_builder_action(env, target, source):
28a3cc
-    ofile = open(str(target[0]), 'wb')
28a3cc
+    ofile = open(str(target[0]), 'w')
28a3cc
     try:
28a3cc
         for s in _integration_tests:
28a3cc
-            print '\t' + str(s)
28a3cc
+            print('\t' + str(s))
28a3cc
             ofile.write('%s\n' % s)
28a3cc
     finally:
28a3cc
         ofile.close()
28a3cc
diff --git a/site_scons/site_tools/mongo_unittest.py b/site_scons/site_tools/mongo_unittest.py
28a3cc
index ec99ab2d45..a4185a6b41 100644
28a3cc
--- a/site_scons/site_tools/mongo_unittest.py
28a3cc
+++ b/site_scons/site_tools/mongo_unittest.py
28a3cc
@@ -11,10 +11,10 @@ def register_unit_test(env, test):
28a3cc
     env.Alias('$UNITTEST_ALIAS', test)
28a3cc
 
28a3cc
 def unit_test_list_builder_action(env, target, source):
28a3cc
-    ofile = open(str(target[0]), 'wb')
28a3cc
+    ofile = open(str(target[0]), 'w')
28a3cc
     try:
28a3cc
         for s in _unittests:
28a3cc
-            print '\t' + str(s)
28a3cc
+            print('\t' + str(s))
28a3cc
             ofile.write('%s\n' % s)
28a3cc
     finally:
28a3cc
         ofile.close()
28a3cc
diff --git a/site_scons/site_tools/split_dwarf.py b/site_scons/site_tools/split_dwarf.py
28a3cc
index 95130c9e9a..c02d78619f 100644
28a3cc
--- a/site_scons/site_tools/split_dwarf.py
28a3cc
+++ b/site_scons/site_tools/split_dwarf.py
28a3cc
@@ -52,7 +52,7 @@ def generate(env):
28a3cc
 
28a3cc
     for object_builder in SCons.Tool.createObjBuilders(env):
28a3cc
         emitterdict = object_builder.builder.emitter
28a3cc
-        for suffix in emitterdict.iterkeys():
28a3cc
+        for suffix in emitterdict.keys():
28a3cc
             if not suffix in suffixes:
28a3cc
                 continue
28a3cc
             base = emitterdict[suffix]
28a3cc
diff --git a/site_scons/site_tools/thin_archive.py b/site_scons/site_tools/thin_archive.py
28a3cc
index 511c0ef6e5..0d8a83b83a 100644
28a3cc
--- a/site_scons/site_tools/thin_archive.py
28a3cc
+++ b/site_scons/site_tools/thin_archive.py
28a3cc
@@ -41,7 +41,7 @@ def exists(env):
28a3cc
     for line in pipe.stdout:
28a3cc
         if isgnu:
28a3cc
             continue  # consume all data
28a3cc
-        isgnu = re.search(r'^GNU ar', line)
28a3cc
+        isgnu = re.search(b'^GNU ar', line)
28a3cc
 
28a3cc
     return bool(isgnu)
28a3cc
 
28a3cc
diff --git a/site_scons/site_tools/xcode.py b/site_scons/site_tools/xcode.py
28a3cc
index 9ec68c3547..5ddebb2e00 100644
28a3cc
--- a/site_scons/site_tools/xcode.py
28a3cc
+++ b/site_scons/site_tools/xcode.py
28a3cc
@@ -9,4 +9,4 @@ def generate(env):
28a3cc
 
28a3cc
     if 'DEVELOPER_DIR' in os.environ:
28a3cc
         env['ENV']['DEVELOPER_DIR'] = os.environ['DEVELOPER_DIR']
28a3cc
-        print "NOTE: Xcode detected; propagating DEVELOPER_DIR from shell environment to subcommands"
28a3cc
+        print("NOTE: Xcode detected; propagating DEVELOPER_DIR from shell environment to subcommands")
28a3cc
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
28a3cc
index 426e57cafd..cc09ab4e0e 100644
28a3cc
--- a/src/mongo/SConscript
28a3cc
+++ b/src/mongo/SConscript
28a3cc
@@ -156,7 +156,7 @@ js_engine_ver = get_option("js-engine") if get_option("server-js") == "on" else
28a3cc
 
28a3cc
 # On windows, we need to escape the backslashes in the command-line
28a3cc
 # so that windows paths look okay.
28a3cc
-cmd_line = " ".join(sys.argv).encode('string-escape')
28a3cc
+cmd_line = " ".join(sys.argv).encode('unicode_escape')
28a3cc
 if env.TargetOSIs('windows'):
28a3cc
     cmd_line = cmd_line.replace('\\', r'\\')
28a3cc
 
28a3cc
@@ -602,7 +602,7 @@ env.Append(MODULE_BANNERS = [distsrc.File('README'),
28a3cc
                              distsrc.File('MPL-2')])
28a3cc
 
28a3cc
 # If no module has introduced a file named LICENSE.txt, then inject the AGPL.
28a3cc
-if sum(itertools.imap(lambda x: x.name == "LICENSE.txt", env['MODULE_BANNERS'])) == 0:
28a3cc
+if sum(map(lambda x: x.name == "LICENSE.txt", env['MODULE_BANNERS'])) == 0:
28a3cc
     env.Append(MODULE_BANNERS = [distsrc.File('GNU-AGPL-3.0')])
28a3cc
 
28a3cc
 # All module banners get staged to the top level of the tarfile, so we
28a3cc
@@ -621,7 +621,7 @@ module_banner_transforms = ["--transform %s=$SERVER_DIST_BASENAME" % d for d in
28a3cc
 # Allow modules to map original file name directories to subdirectories
28a3cc
 # within the archive (e.g. { "src/mongo/db/modules/enterprise/docs": "snmp"})
28a3cc
 archive_addition_transforms = []
28a3cc
-for full_dir, archive_dir in env["ARCHIVE_ADDITION_DIR_MAP"].items():
28a3cc
+for full_dir, archive_dir in list(env["ARCHIVE_ADDITION_DIR_MAP"].items()):
28a3cc
   archive_addition_transforms.append("--transform \"%s=$SERVER_DIST_BASENAME/%s\"" %
28a3cc
                                      (full_dir, archive_dir))
28a3cc
 
28a3cc
diff --git a/src/mongo/base/generate_error_codes.py b/src/mongo/base/generate_error_codes.py
28a3cc
index 420ee964ff..b704767a01 100644
28a3cc
--- a/src/mongo/base/generate_error_codes.py
28a3cc
+++ b/src/mongo/base/generate_error_codes.py
28a3cc
@@ -26,6 +26,8 @@
28a3cc
 #    delete this exception statement from all source files in the program,
28a3cc
 #    then also delete it in the license file.
28a3cc
 
28a3cc
+from __future__ import unicode_literals
28a3cc
+
28a3cc
 """Generate error_codes.{h,cpp} from error_codes.err.
28a3cc
 
28a3cc
 Format of error_codes.err:
28a3cc
@@ -93,7 +95,7 @@ def main(argv):
28a3cc
                 categories=error_classes,
28a3cc
                 )
28a3cc
 
28a3cc
-        with open(output, 'wb') as outfile:
28a3cc
+        with open(output, 'w') as outfile:
28a3cc
             outfile.write(text)
28a3cc
 
28a3cc
 def die(message=None):
28a3cc
diff --git a/src/mongo/db/auth/generate_action_types.py b/src/mongo/db/auth/generate_action_types.py
28a3cc
index b712b29666..39252ed293 100755
28a3cc
--- a/src/mongo/db/auth/generate_action_types.py
28a3cc
+++ b/src/mongo/db/auth/generate_action_types.py
28a3cc
@@ -227,7 +227,7 @@ def hasDuplicateActionTypes(actionTypes):
28a3cc
     prevActionType = sortedActionTypes[0]
28a3cc
     for actionType in sortedActionTypes[1:]:
28a3cc
         if actionType == prevActionType:
28a3cc
-            print 'Duplicate actionType %s\n' % actionType
28a3cc
+            print('Duplicate actionType %s\n' % actionType)
28a3cc
             didFail = True
28a3cc
         prevActionType = actionType
28a3cc
 
28a3cc
@@ -240,7 +240,7 @@ def parseActionTypesFromFile(actionTypesFilename):
28a3cc
 
28a3cc
 if __name__ == "__main__":
28a3cc
     if len(sys.argv) != 4:
28a3cc
-        print "Usage: generate_action_types.py <path to action_types.txt> <header file path> <source file path>"
28a3cc
+        print("Usage: generate_action_types.py <path to action_types.txt> <header file path> <source file path>")
28a3cc
         sys.exit(-1)
28a3cc
 
28a3cc
     actionTypes = parseActionTypesFromFile(sys.argv[1])
28a3cc
diff --git a/src/mongo/db/fts/generate_stop_words.py b/src/mongo/db/fts/generate_stop_words.py
28a3cc
index e0dc801ca9..e0aad760e8 100644
28a3cc
--- a/src/mongo/db/fts/generate_stop_words.py
28a3cc
+++ b/src/mongo/db/fts/generate_stop_words.py
28a3cc
@@ -7,7 +7,7 @@ def generate( header, source, language_files ):
28a3cc
     for x in language_files:
28a3cc
         print( "\t%s" % x )
28a3cc
 
28a3cc
-    out = open( header, "wb" )
28a3cc
+    out = open( header, "w" )
28a3cc
     out.write( """
28a3cc
 #pragma once
28a3cc
 #include <set>
28a3cc
@@ -24,7 +24,7 @@ namespace fts {
28a3cc
 
28a3cc
 
28a3cc
 
28a3cc
-    out = open( source, "wb" )
28a3cc
+    out = open( source, "w" )
28a3cc
     out.write( '#include "%s"' % header.rpartition( "/" )[2].rpartition( "\\" )[2] )
28a3cc
     out.write( """
28a3cc
 namespace mongo {
28a3cc
@@ -40,7 +40,7 @@ namespace fts {
28a3cc
         out.write( '  // %s\n' % l_file )
28a3cc
         out.write( '  {\n' )
28a3cc
         out.write( '   const char* const words[] = {\n' )
28a3cc
-        for word in open( l_file, "rb" ):
28a3cc
+        for word in open( l_file, "r" ):
28a3cc
             out.write( '       "%s",\n' % word.strip() )
28a3cc
         out.write( '   };\n' )
28a3cc
         out.write( '   const size_t wordcnt = sizeof(words) / sizeof(words[0]);\n' )
28a3cc
diff --git a/src/mongo/db/fts/unicode/gen_diacritic_map.py b/src/mongo/db/fts/unicode/gen_diacritic_map.py
28a3cc
index 08cfa95cda..7c623aff60 100644
28a3cc
--- a/src/mongo/db/fts/unicode/gen_diacritic_map.py
28a3cc
+++ b/src/mongo/db/fts/unicode/gen_diacritic_map.py
28a3cc
@@ -45,7 +45,7 @@ def add_diacritic_mapping(codepoint):
28a3cc
     # c : recomposed unicode character with diacritics removed
28a3cc
     a = chr(codepoint)
28a3cc
     d = normalize('NFD', a)
28a3cc
-    r = u''
28a3cc
+    r = ''
28a3cc
 
28a3cc
     for i in range(len(d)):
28a3cc
         if ord(d[i]) not in diacritics:
28a3cc
diff --git a/src/mongo/db/query/collation/generate_icu_init_cpp.py b/src/mongo/db/query/collation/generate_icu_init_cpp.py
28a3cc
index 8ae084aeec..7c576f6ffe 100755
28a3cc
--- a/src/mongo/db/query/collation/generate_icu_init_cpp.py
28a3cc
+++ b/src/mongo/db/query/collation/generate_icu_init_cpp.py
28a3cc
@@ -26,6 +26,9 @@
28a3cc
 #    delete this exception statement from all source files in the program,
28a3cc
 #    then also delete it in the license file.
28a3cc
 
28a3cc
+from __future__ import unicode_literals
28a3cc
+
28a3cc
+import array
28a3cc
 import optparse
28a3cc
 import os
28a3cc
 import sys
28a3cc
@@ -110,8 +113,8 @@ MONGO_INITIALIZER(LoadICUData)(InitializerContext* context) {
28a3cc
 '''
28a3cc
     decimal_encoded_data = ''
28a3cc
     with open(data_file_path, 'rb') as data_file:
28a3cc
-        decimal_encoded_data = ','.join([str(ord(byte)) for byte in data_file.read()])
28a3cc
-    with open(cpp_file_path, 'wb') as cpp_file:
28a3cc
+        decimal_encoded_data = ','.join([str(byte) for byte in array.array("B", data_file.read()).tolist()])
28a3cc
+    with open(cpp_file_path, 'w') as cpp_file:
28a3cc
         cpp_file.write(source_template % dict(decimal_encoded_data=decimal_encoded_data))
28a3cc
 
28a3cc
 if __name__ == '__main__':