Bug 1280947 - Support tuples for script arguments; r?automatedtester draft
authorAndreas Tolfsen <ato@mozilla.com>
Thu, 25 Aug 2016 14:13:59 +0100
changeset 405525 a05fe11bfc556bb31c471f29aaa9bab40160aa5f
parent 405524 9e95fb062fbe13ab185c052b68d6c7362150ec20
child 405526 12b9f7ab391f72405d6fcd9e9d34af24448a1d6e
push id27513
push userbmo:ato@mozilla.com
push dateThu, 25 Aug 2016 16:05:24 +0000
reviewersautomatedtester
bugs1280947
milestone51.0a1
Bug 1280947 - Support tuples for script arguments; r?automatedtester 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,