Bug 1280947 - Support tuples for script arguments; r=automatedtester a=testonly
☠☠ backed out by 0a787a252077 ☠ ☠
authorAndreas Tolfsen <ato@mozilla.com>
Thu, 25 Aug 2016 14:13:59 +0100
changeset 350041 e758a626321d6ff1ea30a8178d8ec5fc35e971c4
parent 350040 3933108db994ae717529dd9df2c641e08b5c92f3
child 350042 ed0707148ece695a4a6063f8a06ce9bceb94a6b5
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersautomatedtester, testonly
bugs1280947
milestone50.0a2
Bug 1280947 - Support tuples for script arguments; r=automatedtester a=testonly Tuples is are most commonly used in the Python standard library to represent function argument iterables. This patch changes the Marionette Python client to support both tuples and lists. MozReview-Commit-ID: 9c6SGeWEIBL
testing/marionette/client/marionette_driver/marionette.py
--- a/testing/marionette/client/marionette_driver/marionette.py
+++ b/testing/marionette/client/marionette_driver/marionette.py
@@ -789,33 +789,33 @@ class Marionette(object):
         script = """
         let value = {
           'url': document.nodePrincipal.URI.spec,
           'appId': document.nodePrincipal.appId,
           'isInIsolatedMozBrowserElement': document.nodePrincipal.isInIsolatedMozBrowserElement,
           'type': arguments[0]
         };
         return value;"""
-        with self.using_context('content'):
-            value = self.execute_script(script, script_args=[perm], sandbox='system')
+        with self.using_context("content"):
+            value = self.execute_script(script, script_args=(perm,), sandbox="system")
 
-        with self.using_context('chrome'):
+        with self.using_context("chrome"):
             permission = self.execute_script("""
                 Components.utils.import("resource://gre/modules/Services.jsm");
                 let perm = arguments[0];
                 let secMan = Services.scriptSecurityManager;
                 let attrs = {appId: perm.appId,
                             inIsolatedMozBrowser: perm.isInIsolatedMozBrowserElement};
                 let principal = secMan.createCodebasePrincipal(
                                 Services.io.newURI(perm.url, null, null),
                                 attrs);
                 let testPerm = Services.perms.testPermissionFromPrincipal(
                                principal, perm.type);
                 return testPerm;
-                """, script_args=[value])
+                """, script_args=(value,))
         return permission
 
     def push_permission(self, perm, allow):
         script = """
         let allow = arguments[0];
         if (typeof(allow) == "boolean") {
             if (allow) {
               allow = Components.interfaces.nsIPermissionManager.ALLOW_ACTION;
@@ -845,42 +845,42 @@ class Marionette(object):
           'url': document.nodePrincipal.URI.spec,
           'appId': document.nodePrincipal.appId,
           'isInIsolatedMozBrowserElement': document.nodePrincipal.isInIsolatedMozBrowserElement,
           'type': perm_type,
           'action': allow
         };
         return value;
         """
-        with self.using_context('content'):
-            perm = self.execute_script(script, script_args=[allow, perm], sandbox='system')
+        with self.using_context("content"):
+            perm = self.execute_script(script, script_args=(allow, perm,), sandbox="system")
 
-        current_perm = self.get_permission(perm['type'])
-        if current_perm == perm['action']:
-            with self.using_context('content'):
+        current_perm = self.get_permission(perm["type"])
+        if current_perm == perm["action"]:
+            with self.using_context("content"):
                 self.execute_script("""
                     Components.utils.import("resource://gre/modules/Services.jsm");
                     Services.obs.removeObserver(window.wrappedJSObject.permObserver,
                                                 "perm-changed");
-                    """, sandbox='system')
+                    """, sandbox="system")
             return
 
-        with self.using_context('chrome'):
+        with self.using_context("chrome"):
             self.execute_script("""
                 Components.utils.import("resource://gre/modules/Services.jsm");
                 let perm = arguments[0];
                 let secMan = Services.scriptSecurityManager;
                 let attrs = {appId: perm.appId,
                              inIsolatedMozBrowser: perm.isInIsolatedMozBrowserElement};
                 let principal = secMan.createCodebasePrincipal(Services.io.newURI(perm.url,
                                                                                   null, null),
                                                                                   attrs);
                 Services.perms.addFromPrincipal(principal, perm.type, perm.action);
                 return true;
-                """, script_args=[perm])
+                """, script_args=(perm,))
 
         with self.using_context("content"):
             self.execute_async_script("""
                 let start = new Date();
                 let end = new Date(start.valueOf() + 5000);
                 let wait = function() {
                   let now = new Date();
                   if (window.wrappedJSObject.permChanged || end >= now) {
@@ -923,82 +923,82 @@ class Marionette(object):
         Usage example::
 
             marionette.get_pref("browser.tabs.warnOnClose")
         """
         with self.using_context(self.CONTEXT_CONTENT):
             pref_value = self.execute_script("""
                 Components.utils.import("resource://gre/modules/Preferences.jsm");
                 return Preferences.get(arguments[0], null);
-                """, script_args=[pref], sandbox="system")
+                """, script_args=(pref,), sandbox="system")
             return pref_value
 
     def clear_pref(self, pref):
         with self.using_context(self.CONTEXT_CHROME):
             self.execute_script("""
                Components.utils.import("resource://gre/modules/Preferences.jsm");
                Preferences.reset(arguments[0]);
-               """, script_args=[pref])
+               """, script_args=(pref,))
 
     def set_pref(self, pref, value):
         with self.using_context(self.CONTEXT_CHROME):
             if value is None:
                 self.clear_pref(pref)
                 return
 
             self.execute_script("""
                 Components.utils.import("resource://gre/modules/Preferences.jsm");
                 Preferences.set(arguments[0], arguments[1]);
-                """, script_args=[pref, value])
+                """, script_args=(pref, value,))
 
     def set_prefs(self, prefs):
-        '''Sets preferences.
+        """Sets preferences.
 
         If the value of the preference to be set is None, reset the preference
         to its default value. If no default value exists, the preference will
         cease to exist.
 
-        :param prefs: A dict containing one or more preferences and their values
-        to be set.
+        :param prefs: A dict containing one or more preferences and
+            their values to be set.
 
         Usage example::
 
-          marionette.set_prefs({'browser.tabs.warnOnClose': True})
+            marionette.set_prefs({"browser.tabs.warnOnClose": True})
 
-        '''
+        """
         for pref, value in prefs.items():
             self.set_pref(pref, value)
 
     @contextmanager
     def using_prefs(self, prefs):
-        '''Sets preferences for code being executed in a `with` block,
+        """Sets preferences for code being executed in a `with` block,
         and restores them on exit.
 
         :param prefs: A dict containing one or more preferences and their values
         to be set.
 
         Usage example::
 
-          with marionette.using_prefs({'browser.tabs.warnOnClose': True}):
-              # ... do stuff ...
+            with marionette.using_prefs({"browser.tabs.warnOnClose": True}):
+                # ... do stuff ...
 
-        '''
+        """
         original_prefs = {p: self.get_pref(p) for p in prefs}
         self.set_prefs(prefs)
 
         try:
             yield
         finally:
             self.set_prefs(original_prefs)
 
     @do_process_check
     def enforce_gecko_prefs(self, prefs):
-        """
-        Checks if the running instance has the given prefs. If not, it will kill the
-        currently running instance, and spawn a new instance with the requested preferences.
+        """Checks if the running instance has the given prefs. If not,
+        it will kill the currently running instance, and spawn a new
+        instance with the requested preferences.
 
         : param prefs: A dictionary whose keys are preference names.
         """
         if not self.instance:
             raise errors.MarionetteException("enforce_gecko_prefs() can only be called "
                                              "on Gecko instances launched by Marionette")
         pref_exists = True
         self.set_context(self.CONTEXT_CHROME)
@@ -1532,45 +1532,43 @@ class Marionette(object):
                     unwrapped = HTMLElement(self, value[key])
                     break
                 else:
                     unwrapped[key] = self._from_json(value[key])
         else:
             unwrapped = value
         return unwrapped
 
-    def execute_js_script(self, script, script_args=None, async=True,
+    def execute_js_script(self, script, script_args=(), async=True,
                           new_sandbox=True, script_timeout=None,
                           inactivity_timeout=None, filename=None,
                           sandbox='default'):
-        if script_args is None:
-            script_args = []
         args = self._to_json(script_args)
         body = {"script": script,
                 "args": args,
                 "async": async,
                 "newSandbox": new_sandbox,
                 "scriptTimeout": script_timeout,
                 "inactivityTimeout": inactivity_timeout,
                 "filename": filename,
                 "line": None}
         rv = self._send_message("executeJSScript", body, key="value")
         return self._from_json(rv)
 
-    def execute_script(self, script, script_args=None, new_sandbox=True,
+    def execute_script(self, script, script_args=(), new_sandbox=True,
                        sandbox="default", script_timeout=None):
         """Executes a synchronous JavaScript script, and returns the
         result (or None if the script does return a value).
 
         The script is executed in the context set by the most recent
         set_context() call, or to the CONTEXT_CONTENT context if set_context()
         has not been called.
 
         :param script: A string containing the JavaScript to execute.
-        :param script_args: A list of arguments to pass to the script.
+        :param script_args: An interable of arguments to pass to the script.
         :param sandbox: A tag referring to the sandbox you wish to use;
             if you specify a new tag, a new sandbox will be created.
             If you use the special tag `system`, the sandbox will
             be created using the system principal which has elevated
             privileges.
         :param new_sandbox: If False, preserve global variables from
             the last execute_*script call. This is True by default, in which
             case no globals are preserved.
@@ -1583,20 +1581,20 @@ class Marionette(object):
             assert result == 1
 
         You can use the `script_args` parameter to pass arguments to the
         script:
 
         ::
 
             result = marionette.execute_script("return arguments[0] + arguments[1];",
-                                               script_args=[2, 3])
+                                               script_args=(2, 3,))
             assert result == 5
             some_element = marionette.find_element(By.ID, "someElement")
-            sid = marionette.execute_script("return arguments[0].id;", script_args=[some_element])
+            sid = marionette.execute_script("return arguments[0].id;", script_args=(some_element,))
             assert some_element.get_attribute("id") == sid
 
         Scripts wishing to access non-standard properties of the window
         object must use window.wrappedJSObject:
 
         ::
 
             result = marionette.execute_script('''
@@ -1613,43 +1611,41 @@ class Marionette(object):
 
         ::
 
             marionette.execute_script("global.test1 = 'foo';")
             result = self.marionette.execute_script("return global.test1;", new_sandbox=False)
             assert result == "foo"
 
         """
-        if script_args is None:
-            script_args = []
         args = self._to_json(script_args)
         stack = traceback.extract_stack()
         frame = stack[-2:-1][0]  # grab the second-to-last frame
         body = {"script": script,
                 "args": args,
                 "newSandbox": new_sandbox,
                 "sandbox": sandbox,
                 "scriptTimeout": script_timeout,
                 "line": int(frame[1]),
                 "filename": os.path.basename(frame[0])}
         rv = self._send_message("executeScript", body, key="value")
         return self._from_json(rv)
 
-    def execute_async_script(self, script, script_args=None, new_sandbox=True,
+    def execute_async_script(self, script, script_args=(), new_sandbox=True,
                              sandbox="default", script_timeout=None,
                              debug_script=False):
         """Executes an asynchronous JavaScript script, and returns the
         result (or None if the script does return a value).
 
         The script is executed in the context set by the most recent
         set_context() call, or to the CONTEXT_CONTENT context if
         set_context() has not been called.
 
         :param script: A string containing the JavaScript to execute.
-        :param script_args: A list of arguments to pass to the script.
+        :param script_args: An interable of arguments to pass to the script.
         :param sandbox: A tag referring to the sandbox you wish to use; if
             you specify a new tag, a new sandbox will be created.  If you
             use the special tag `system`, the sandbox will be created
             using the system principal which has elevated privileges.
         :param new_sandbox: If False, preserve global variables from
             the last execute_*script call. This is True by default,
             in which case no globals are preserved.
         :param debug_script: Capture javascript exceptions when in
@@ -1663,18 +1659,16 @@ class Marionette(object):
             result = self.marionette.execute_async_script('''
               // this script waits 5 seconds, and then returns the number 1
               setTimeout(function() {
                 marionetteScriptFinished(1);
               }, 5000);
             ''')
             assert result == 1
         """
-        if script_args is None:
-            script_args = []
         args = self._to_json(script_args)
         stack = traceback.extract_stack()
         frame = stack[-2:-1][0]  # grab the second-to-last frame
         body = {"script": script,
                 "args": args,
                 "newSandbox": new_sandbox,
                 "sandbox": sandbox,
                 "scriptTimeout": script_timeout,