+++ /dev/null
-#-------------------------------------------------------------------------------
-# elftools: common/py3compat.py
-#
-# Python 2/3 compatibility code
-#
-# Eli Bendersky (eliben@gmail.com)
-# This code is in the public domain
-#-------------------------------------------------------------------------------
-import sys
-PY3 = sys.version_info[0] == 3
-assert PY3, '''\
-Python 2 is no longer supported by pyelftools; if you need to use Python 2,
-please download an older pyelftools version (such as version 0.29).
-'''
-
-
-if PY3:
-    # Functions for acting on bytestrings and strings. In Python 2 and 3,
-    # strings and bytes are the same and chr/ord can be used to convert between
-    # numeric byte values and their string representations. In Python 3, bytes
-    # and strings are different types and bytes hold numeric values when
-    # iterated over.
-
-
-    def bytes2str(b): return b.decode('latin-1')
-    def str2bytes(s): return s.encode('latin-1')
 
         result.update(d)
     return result
 
+def bytes2str(b):
+    """Decode a bytes object into a string."""
+    return b.decode('latin-1')
 
 def bytelist2string(bytelist):
     """ Convert a list of byte values (e.g. [0x10 0x20 0x00]) to a bytes object
 
 # Eli Bendersky (eliben@gmail.com)
 # This code is in the public domain
 #-------------------------------------------------------------------------------
-from ..common.py3compat import bytes2str
+from ..common.utils import bytes2str
 
 cpp_symbols = dict(
     pointer   = "*",
 def parse_cpp_datatype(var_die):
     """Given a DIE that describes a variable, a parameter, or a member
     with DW_AT_type in it, tries to return the C++ datatype as a string
-    
+
     Returns a TypeDesc.
 
     Does not follow typedefs, doesn't  resolve array element types
     # From this point on, type_die doesn't change
     t.tag = _strip_type_tag(type_die)
     t.modifiers = tuple(mods)
-    
+
     if t.tag in ('ptr_to_member', 'subroutine'):
         if t.tag == 'ptr_to_member':
             ptr_prefix = DIE_name(type_die.get_DIE_from_attribute('DW_AT_containing_type')) + "::"
         # If unnamed scope, fall back to scope type - like "structure "
         parent = parent.get_parent()
     t.scopes = tuple(scopes)
-    
-    return t  
+
+    return t
 
 #--------------------------------------------------
 
         self.name = None
         self.modifiers = () # Reads left to right
         self.scopes = () # Reads left to right
-        self.tag = None 
+        self.tag = None
         self.dimensions = None
 
     def __str__(self):
         class_spec = ClassDesc()
         class_spec.scopes = this_type.scopes + (this_type.name,)
         class_spec.const_member = any(("const", "pointer") == this_type.modifiers[i:i+2]
-            for i in range(len(this_type.modifiers))) # const -> pointer -> const for this arg of const 
+            for i in range(len(this_type.modifiers))) # const -> pointer -> const for this arg of const
         return class_spec
 
     # Check the parent element chain - could be a class
     if type_die.tag == 'DW_TAG_structure_type':
         members = tuple(die for die in type_die.iter_children() if die.tag == "DW_TAG_member")
         return len(members) == 2 and safe_DIE_name(members[0]) == "__pfn" and safe_DIE_name(members[1]) == "__delta"
-    return False                        
+    return False
 
 def _strip_type_tag(die):
     """Given a DIE with DW_TAG_foo_type, returns foo"""
 
 from .constants import *
 from .dwarf_expr import DWARFExprParser
 from .die import DIE
-from ..common.utils import preserve_stream_pos, dwarf_assert
-from ..common.py3compat import bytes2str
+from ..common.utils import preserve_stream_pos, dwarf_assert, bytes2str
 from .callframe import instruction_name, CIE, FDE
 
 
 
 import os
 
 from ..common.exceptions import DWARFError
-from ..common.py3compat import bytes2str
-from ..common.utils import struct_parse, preserve_stream_pos
+from ..common.utils import bytes2str, struct_parse, preserve_stream_pos
 from .enums import DW_FORM_raw2name
 from .dwarf_util import _resolve_via_offset_table, _get_base_offset
 
 
 # Eli Bendersky (eliben@gmail.com)
 # This code is in the public domain
 #-------------------------------------------------------------------------------
-from ..common.py3compat import bytes2str
-from ..common.utils import struct_parse, bytes2hex, roundup
+from ..common.utils import struct_parse, bytes2hex, roundup, bytes2str
 from ..construct import CString
 
 
 
 # examples/ dir of the source distribution.
 sys.path[0:0] = ['.', '..']
 
-from elftools.common.py3compat import bytes2str
+from elftools.common.utils import bytes2str
 from elftools.dwarf.descriptions import describe_form_class
 from elftools.elf.elffile import ELFFile
 
 
 sys.path[0:0] = ['.', '..']
 
 from elftools.elf.elffile import ELFFile
-from elftools.common.py3compat import bytes2str
+from elftools.common.utils import bytes2str
 
 def process_file(filename):
     print('Processing file:', filename)
 
 
 from elftools import __version__
 from elftools.common.exceptions import DWARFError, ELFError
-from elftools.common.py3compat import bytes2str
+from elftools.common.utils import bytes2str
 from elftools.elf.elffile import ELFFile
 from elftools.dwarf.locationlists import LocationParser, LocationEntry, LocationExpr, LocationViewPair, BaseAddressEntry as LocBaseAddressEntry
 from elftools.dwarf.ranges import RangeEntry # ranges.BaseAddressEntry collides with the one above
 
 
 from elftools import __version__
 from elftools.common.exceptions import ELFError
-from elftools.common.py3compat import (
-         bytes2str, str2bytes)
-from elftools.common.utils import iterbytes
+from elftools.common.utils import bytes2str, iterbytes
 from elftools.elf.elffile import ELFFile
 from elftools.elf.dynamic import DynamicSection, DynamicSegment
 from elftools.elf.enums import ENUM_D_TAG
 
 import unittest
 
 from elftools.elf.elffile import ELFFile
-from elftools.common.py3compat import bytes2str
+from elftools.common.utils import bytes2str
 
 class TestCacheLUTandDIEref(unittest.TestCase):
     def dprint(self, list):
 
       print('[cmd]', ' '.join(popen_cmd))
     proc = subprocess.Popen(popen_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     proc_stdout = proc.communicate()[0]
-    from elftools.common.py3compat import bytes2str
-    return proc.returncode, bytes2str(proc_stdout)
+    return proc.returncode, proc_stdout.decode('latin-1')
 
 
 def is_in_rootdir():