Favor Python3 constructs and Python 2.7 compatibility (#8290)

Cr-Mirrored-From: https://chromium.googlesource.com/external/github.com/SeleniumHQ/selenium
Cr-Mirrored-Commit: 9e7535205647d710c1f250065edec37f6f047129
diff --git a/selenium/webdriver/common/keys.py b/selenium/webdriver/common/keys.py
index cd3bb76..76630bb 100644
--- a/selenium/webdriver/common/keys.py
+++ b/selenium/webdriver/common/keys.py
@@ -19,78 +19,76 @@
 The Keys implementation.
 """
 
-from __future__ import unicode_literals
-
 
 class Keys(object):
     """
     Set of special keys codes.
     """
 
-    NULL = '\ue000'
-    CANCEL = '\ue001'  # ^break
-    HELP = '\ue002'
-    BACKSPACE = '\ue003'
+    NULL = u'\ue000'
+    CANCEL = u'\ue001'  # ^break
+    HELP = u'\ue002'
+    BACKSPACE = u'\ue003'
     BACK_SPACE = BACKSPACE
-    TAB = '\ue004'
-    CLEAR = '\ue005'
-    RETURN = '\ue006'
-    ENTER = '\ue007'
-    SHIFT = '\ue008'
+    TAB = u'\ue004'
+    CLEAR = u'\ue005'
+    RETURN = u'\ue006'
+    ENTER = u'\ue007'
+    SHIFT = u'\ue008'
     LEFT_SHIFT = SHIFT
-    CONTROL = '\ue009'
+    CONTROL = u'\ue009'
     LEFT_CONTROL = CONTROL
-    ALT = '\ue00a'
+    ALT = u'\ue00a'
     LEFT_ALT = ALT
-    PAUSE = '\ue00b'
-    ESCAPE = '\ue00c'
-    SPACE = '\ue00d'
-    PAGE_UP = '\ue00e'
-    PAGE_DOWN = '\ue00f'
-    END = '\ue010'
-    HOME = '\ue011'
-    LEFT = '\ue012'
+    PAUSE = u'\ue00b'
+    ESCAPE = u'\ue00c'
+    SPACE = u'\ue00d'
+    PAGE_UP = u'\ue00e'
+    PAGE_DOWN = u'\ue00f'
+    END = u'\ue010'
+    HOME = u'\ue011'
+    LEFT = u'\ue012'
     ARROW_LEFT = LEFT
-    UP = '\ue013'
+    UP = u'\ue013'
     ARROW_UP = UP
-    RIGHT = '\ue014'
+    RIGHT = u'\ue014'
     ARROW_RIGHT = RIGHT
-    DOWN = '\ue015'
+    DOWN = u'\ue015'
     ARROW_DOWN = DOWN
-    INSERT = '\ue016'
-    DELETE = '\ue017'
-    SEMICOLON = '\ue018'
-    EQUALS = '\ue019'
+    INSERT = u'\ue016'
+    DELETE = u'\ue017'
+    SEMICOLON = u'\ue018'
+    EQUALS = u'\ue019'
 
-    NUMPAD0 = '\ue01a'  # number pad keys
-    NUMPAD1 = '\ue01b'
-    NUMPAD2 = '\ue01c'
-    NUMPAD3 = '\ue01d'
-    NUMPAD4 = '\ue01e'
-    NUMPAD5 = '\ue01f'
-    NUMPAD6 = '\ue020'
-    NUMPAD7 = '\ue021'
-    NUMPAD8 = '\ue022'
-    NUMPAD9 = '\ue023'
-    MULTIPLY = '\ue024'
-    ADD = '\ue025'
-    SEPARATOR = '\ue026'
-    SUBTRACT = '\ue027'
-    DECIMAL = '\ue028'
-    DIVIDE = '\ue029'
+    NUMPAD0 = u'\ue01a'  # number pad keys
+    NUMPAD1 = u'\ue01b'
+    NUMPAD2 = u'\ue01c'
+    NUMPAD3 = u'\ue01d'
+    NUMPAD4 = u'\ue01e'
+    NUMPAD5 = u'\ue01f'
+    NUMPAD6 = u'\ue020'
+    NUMPAD7 = u'\ue021'
+    NUMPAD8 = u'\ue022'
+    NUMPAD9 = u'\ue023'
+    MULTIPLY = u'\ue024'
+    ADD = u'\ue025'
+    SEPARATOR = u'\ue026'
+    SUBTRACT = u'\ue027'
+    DECIMAL = u'\ue028'
+    DIVIDE = u'\ue029'
 
-    F1 = '\ue031'  # function  keys
-    F2 = '\ue032'
-    F3 = '\ue033'
-    F4 = '\ue034'
-    F5 = '\ue035'
-    F6 = '\ue036'
-    F7 = '\ue037'
-    F8 = '\ue038'
-    F9 = '\ue039'
-    F10 = '\ue03a'
-    F11 = '\ue03b'
-    F12 = '\ue03c'
+    F1 = u'\ue031'  # function  keys
+    F2 = u'\ue032'
+    F3 = u'\ue033'
+    F4 = u'\ue034'
+    F5 = u'\ue035'
+    F6 = u'\ue036'
+    F7 = u'\ue037'
+    F8 = u'\ue038'
+    F9 = u'\ue039'
+    F10 = u'\ue03a'
+    F11 = u'\ue03b'
+    F12 = u'\ue03c'
 
-    META = '\ue03d'
-    COMMAND = '\ue03d'
+    META = u'\ue03d'
+    COMMAND = u'\ue03d'
diff --git a/selenium/webdriver/common/window.py b/selenium/webdriver/common/window.py
index 73f5998..951357b 100644
--- a/selenium/webdriver/common/window.py
+++ b/selenium/webdriver/common/window.py
@@ -19,11 +19,9 @@
 The WindowTypes implementation.
 """
 
-from __future__ import unicode_literals
-
 
 class WindowTypes(object):
     """Set of supported window types."""
 
-    TAB = 'tab'
-    WINDOW = 'window'
+    TAB = u'tab'
+    WINDOW = u'window'
diff --git a/selenium/webdriver/firefox/firefox_profile.py b/selenium/webdriver/firefox/firefox_profile.py
index a942d34..afb325f 100644
--- a/selenium/webdriver/firefox/firefox_profile.py
+++ b/selenium/webdriver/firefox/firefox_profile.py
@@ -15,8 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-from __future__ import with_statement
-
 import base64
 import copy
 import json
@@ -26,13 +24,9 @@
 import sys
 import tempfile
 import zipfile
-
-try:
-    from cStringIO import StringIO as BytesIO
-except ImportError:
-    from io import BytesIO
-
+from io import BytesIO
 from xml.dom import minidom
+
 from selenium.common.exceptions import WebDriverException
 
 
@@ -309,6 +303,7 @@
             if zipfile.is_zipfile(addon_path):
                 # Bug 944361 - We cannot use 'with' together with zipFile because
                 # it will cause an exception thrown in Python 2.6.
+                # TODO: use with statement when Python 2.x is no longer supported
                 try:
                     compressed_file = zipfile.ZipFile(addon_path, 'r')
                     if 'manifest.json' in compressed_file.namelist():
diff --git a/selenium/webdriver/remote/webelement.py b/selenium/webdriver/remote/webelement.py
index c68e39d..f29b89b 100644
--- a/selenium/webdriver/remote/webelement.py
+++ b/selenium/webdriver/remote/webelement.py
@@ -21,6 +21,7 @@
 import pkgutil
 import warnings
 import zipfile
+from io import BytesIO
 
 from selenium.common.exceptions import WebDriverException
 from selenium.webdriver.common.by import By
@@ -35,14 +36,11 @@
 
 try:
     from base64 import encodebytes
-except ImportError:  # 3+
+except ImportError:  # Python 2
     from base64 import encodestring as encodebytes
 
-try:
-    from StringIO import StringIO as IOStream
-except ImportError:  # 3+
-    from io import BytesIO as IOStream
 
+# TODO: when dropping Python 2.7, use built in importlib_resources.files
 # not relying on __package__ here as it can be `None` in some situations (see #4558)
 _pkg = '.'.join(__name__.split('.')[:-1])
 getAttribute_js = pkgutil.get_data(_pkg, 'getAttribute.js').decode('utf8')
@@ -752,7 +750,7 @@
         return int(hashlib.md5(self._id.encode('utf-8')).hexdigest(), 16)
 
     def _upload(self, filename):
-        fp = IOStream()
+        fp = BytesIO()
         zipped = zipfile.ZipFile(fp, 'w', zipfile.ZIP_DEFLATED)
         zipped.write(filename, os.path.split(filename)[1])
         zipped.close()