Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

bug 692091 - mozharness code for peptest. p=ahal, r=me

  • Loading branch information...
commit 4e7318c67f6c283db7344a1163b652195a3a3838 1 parent e9eead4
Aki Sasaki authored November 04, 2011
52  configs/peptest/prod_config.py
... ...
@@ -0,0 +1,52 @@
  1
+# This is a template config file for peptest production
  2
+
  3
+# The peptest mozharness script is set up so that specifying None
  4
+# is the same as not specifying the option at all
  5
+import os
  6
+
  7
+config = {
  8
+    # mozharness script options
  9
+    "base_work_dir": os.getcwd(),
  10
+    "work_dir": "build",
  11
+    "log_name": "pep",
  12
+    "log_level": "info",
  13
+    "test_url": "url_to_packaged_tests",
  14
+    # path or url to a zip or folder containing the mozbase packages
  15
+    "mozbase_path": "url_to_mozbase_zip",
  16
+    # path or url to a zip or folder containing peptest
  17
+    "peptest_path": "url_to_peptest_zip",
  18
+
  19
+    # peptest options
  20
+    "appname": "url_to_application",    # i.e the firefox build on ftp.m.o
  21
+    # defaults to firefox, can also be thunderbird, fennec, etc.
  22
+    "app": "firefox",
  23
+    # if test_url is specified, this should be the relative
  24
+    # path to the manifest inside the extracted test directory
  25
+    # otherwise, should be path to a test manifest on the local file system
  26
+    "test_manifest": "path_to_test_manifest",
  27
+    # optional, use an existing profile (temp profile created by default)
  28
+    "profile_path": None,
  29
+    # global timeout in seconds (without output)
  30
+    "timeout": 60,
  31
+    # if specified, creates a webserver for hosting test
  32
+    # related files at this document root
  33
+    "server_path": None,
  34
+    "server_port": None,
  35
+    # EventTracer setting, the threshold to count a failure (ms)
  36
+    "tracer_threshold": 50,
  37
+    # EventTracer setting, interval at which to send tracer events (ms)
  38
+    "tracer_interval": 10,
  39
+    # URL or path to the symbols directory for debugging crashes
  40
+    "symbols_path": None,
  41
+}
  42
+
  43
+# these config options depend on the abs_work_dir option
  44
+abs_work_dir = os.path.abspath(os.path.join(config['base_work_dir'],
  45
+                                            config['work_dir']))
  46
+
  47
+config['virtualenv_path'] = os.path.join(abs_work_dir, "venv")
  48
+# directory to extract tests to
  49
+config['test_install_dir'] = os.path.join(abs_work_dir, "tests")
  50
+# directory to install application to
  51
+config['application_install_dir'] = os.path.join(abs_work_dir,
  52
+                                                 "application")
37  configs/peptest/test_config.py
... ...
@@ -0,0 +1,37 @@
  1
+import os
  2
+
  3
+config = {
  4
+    # mozharness script options
  5
+    "base_work_dir": os.getcwd(),
  6
+    "work_dir": "build",
  7
+    "log_name": "pep",
  8
+    "log_level": "info",
  9
+    "test_url": "https://github.com/downloads/ahal/peptest/tests.zip",
  10
+    "mozbase_path": "https://github.com/mozilla/mozbase/zipball/master",
  11
+    "peptest_path": "https://github.com/mozilla/peptest/zipball/master",
  12
+
  13
+    # peptest options
  14
+    "appname": "ftp://ftp.mozilla.org/pub/firefox/nightly/latest-mozilla-central/firefox-10.0a1.en-US.linux-i686.tar.bz2",
  15
+    "app": "firefox",
  16
+    "test_manifest": "firefox/all_tests.ini", # this is relative to the test folder specified by test_url
  17
+    "profile_path": None,
  18
+    "timeout": 60,
  19
+    "server_path": None,
  20
+    "server_port": None,
  21
+    "tracer_threshold": 50,
  22
+    "tracer_interval": 10,
  23
+    "symbols_path": None,
  24
+
  25
+    # get latest tinderbox options
  26
+    "get_latest_tinderbox_product": "mozilla-central",
  27
+    "get_latest_tinderbox_platform": None,
  28
+    "get_latest_tinderbox_debug_build": False,
  29
+}
  30
+
  31
+abs_work_dir = os.path.abspath(os.path.join(config['base_work_dir'],
  32
+                                            config['work_dir']))
  33
+
  34
+config['virtualenv_path'] = os.path.join(abs_work_dir, "venv")
  35
+config['test_install_dir'] = os.path.join(abs_work_dir, "tests")
  36
+config['application_install_dir'] = os.path.join(abs_work_dir,
  37
+                                                 "application")
56  configs/peptest/user_config.py
... ...
@@ -0,0 +1,56 @@
  1
+# This is a template config file for peptest user
  2
+
  3
+# The peptest mozharness script is set up so that specifying None
  4
+# is the same as not specifying the option at all
  5
+import os
  6
+
  7
+config = {
  8
+    # mozharness script options
  9
+    "base_work_dir": os.getcwd(),
  10
+    "work_dir": "build",
  11
+    "log_name": "pep",
  12
+    "log_level": "info",
  13
+    "test_url": "url_to_packaged_tests",
  14
+    # path or url to a zip or folder containing the mozbase packages
  15
+    "mozbase_path": "url_to_mozbase_zip",
  16
+    # path or url to a zip or folder containing peptest
  17
+    "peptest_path": "url_to_peptest_zip",
  18
+
  19
+    # peptest options
  20
+
  21
+    "appname": "path_to_application_binary",
  22
+    # defaults to firefox, can also be thunderbird, fennec, etc.
  23
+    "app": "firefox",
  24
+    "test_manifest": "path_to_test_manifest",
  25
+    # optional, use an existing profile (temp profile created by default)
  26
+    "profile_path": None,
  27
+    # global timeout in seconds (without output)
  28
+    "timeout": 60,
  29
+    # if specified, creates a webserver for hosting test
  30
+    # related files at this document root
  31
+    "server_path": None,
  32
+    "server_port": None,
  33
+    # EventTracer setting, the threshold to count a failure (ms)
  34
+    "tracer_threshold": 50,
  35
+    # EventTracer setting, interval at which to send tracer events (ms)
  36
+    "tracer_interval": 10,
  37
+    # URL or path to the symbols directory for debugging crashes
  38
+    "symbols_path": None,
  39
+
  40
+    # get latest tinderbox options
  41
+    # (these are only used by the get-latest-tinderbox action)
  42
+    "get_latest_tinderbox_product": "mozilla-central",
  43
+    "get_latest_tinderbox_platform": None, # defaults to current platform
  44
+    "get_latest_tinderbox_debug_build": False,
  45
+}
  46
+
  47
+# these config options depend on the abs_work_dir option
  48
+abs_work_dir = os.path.abspath(os.path.join(config['base_work_dir'],
  49
+                                            config['work_dir']))
  50
+
  51
+config['virtualenv_path'] = os.path.join(abs_work_dir, "venv")
  52
+# directory to extract tests to
  53
+config['test_install_dir'] = os.path.join(abs_work_dir, "tests")
  54
+# directory to install application to
  55
+config['application_install_dir'] = os.path.join(abs_work_dir,
  56
+                                                 "application")
21  mozharness/base/python.py
@@ -61,12 +61,14 @@ class VirtualenvMixin(object):
61 61
      * virtualenv_modules lists the module names.
62 62
      * MODULE_url list points to the module URLs (optional)
63 63
     Requires virtualenv to be in PATH.
  64
+    Depends on OSMixin
64 65
     '''
65 66
     python_paths = {}
66 67
 
67 68
     def query_python_path(self, binary="python"):
68 69
         """Return the path of a binary inside the virtualenv, if
69 70
         c['virtualenv_path'] is set; otherwise return the binary name.
  71
+        Otherwise return None
70 72
         """
71 73
         if binary not in self.python_paths:
72 74
             bin_dir = 'bin'
@@ -76,7 +78,24 @@ def query_python_path(self, binary="python"):
76 78
                 self.python_paths[binary] = os.path.abspath(os.path.join(self.config['virtualenv_path'], bin_dir, binary))
77 79
             else:
78 80
                 self.python_paths[binary] = binary
79  
-        return self.python_paths[binary]
  81
+        return self.which(self.python_paths[binary])
  82
+
  83
+    def query_package(self, package_name, error_level=WARNING):
  84
+        """
  85
+        Returns a list of all installed packages
  86
+        that contain package_name in their name
  87
+        """
  88
+        pip = self.query_python_path("pip")
  89
+        if not pip:
  90
+            self.log("query_package: Program pip not in path", level=error_level)
  91
+            return []
  92
+        output = self.get_output_from_command(pip + " freeze",
  93
+                                              silent=True)
  94
+        if not output:
  95
+            return []
  96
+        packages = output.split()
  97
+        return [package for package in packages
  98
+                if package.lower().find(package_name.lower()) != -1]
80 99
 
81 100
     def create_virtualenv(self):
82 101
         c = self.config
27  mozharness/base/script.py
@@ -73,7 +73,7 @@
73 73
 class OSMixin(object):
74 74
     """Filesystem commands and the like.
75 75
 
76  
-    Currently dependent on LogMixin, and a self.config of some sort.
  76
+    Depends on LogMixin, ShellMixin, and a self.config of some sort.
77 77
     """
78 78
     def mkdir_p(self, path):
79 79
         if not os.path.exists(path):
@@ -161,7 +161,7 @@ def download_file(self, url, file_name=None,
161 161
         try:
162 162
             self.info("Downloading %s" % url)
163 163
             f = urllib2.urlopen(req)
164  
-            local_file = open(file_name, 'w')
  164
+            local_file = open(file_name, 'wb')
165 165
             local_file.write(f.read())
166 166
             local_file.close()
167 167
         except urllib2.HTTPError, e:
@@ -258,6 +258,29 @@ def chdir(self, dir_name, ignore_if_noop=False):
258 258
         else:
259 259
             os.chdir(dir_name)
260 260
 
  261
+    def which(self, program):
  262
+        """
  263
+        OS independent implementation of Unix's which command
  264
+        Takes in a program name
  265
+        Returns path to executable or None
  266
+        """
  267
+        def is_exe(fpath):
  268
+            return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
  269
+
  270
+        if self._is_windows() and not program.endswith(".exe"):
  271
+            program += ".exe"
  272
+        fpath, fname = os.path.split(program)
  273
+        if fpath:
  274
+            if is_exe(program):
  275
+                return program
  276
+        else:
  277
+            env = self.query_env()
  278
+            for path in env["PATH"].split(os.pathsep):
  279
+                exe_file = os.path.join(path, program)
  280
+                if is_exe(exe_file):
  281
+                    return exe_file
  282
+        return None
  283
+
261 284
 # ShellMixin {{{1
262 285
 class ShellMixin(object):
263 286
     """These are very special but very complex methods that, together with
353  scripts/peptest.py
... ...
@@ -0,0 +1,353 @@
  1
+#!/usr/bin/env python
  2
+# ***** BEGIN LICENSE BLOCK *****
  3
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4
+#
  5
+# The contents of this file are subject to the Mozilla Public License Version
  6
+# 1.1 (the "License"); you may not use this file except in compliance with
  7
+# the License. You may obtain a copy of the License at
  8
+# http://www.mozilla.org/MPL/
  9
+#
  10
+# Software distributed under the License is distributed on an "AS IS" basis,
  11
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12
+# for the specific language governing rights and limitations under the
  13
+# License.
  14
+#
  15
+# The Original Code is Peptest Mozharness script.
  16
+#
  17
+# The Initial Developer of the Original Code is
  18
+#   Mozilla Corporation.
  19
+# Portions created by the Initial Developer are Copyright (C) 2011
  20
+# the Initial Developer. All Rights Reserved.
  21
+#
  22
+# Contributor(s):
  23
+#   Andrew Halberstadt <halbersa@gmail.com>
  24
+#
  25
+# Alternatively, the contents of this file may be used under the terms of
  26
+# either the GNU General Public License Version 2 or later (the "GPL"), or
  27
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28
+# in which case the provisions of the GPL or the LGPL are applicable instead
  29
+# of those above. If you wish to allow use of your version of this file only
  30
+# under the terms of either the GPL or the LGPL, and not to allow others to
  31
+# use your version of this file under the terms of the MPL, indicate your
  32
+# decision by deleting the provisions above and replace them with the notice
  33
+# and other provisions required by the GPL or the LGPL. If you do not delete
  34
+# the provisions above, a recipient may use your version of this file under
  35
+# the terms of any one of the MPL, the GPL or the LGPL.
  36
+#
  37
+# ***** END LICENSE BLOCK *****
  38
+
  39
+from mozharness.base.errors import PythonErrorList
  40
+from mozharness.base.log import DEBUG, INFO, WARNING, ERROR, FATAL
  41
+from mozharness.base.python import virtualenv_config_options, VirtualenvMixin
  42
+from mozharness.base.script import BaseScript
  43
+import urlparse
  44
+import tarfile
  45
+import zipfile
  46
+import platform
  47
+import os
  48
+import sys
  49
+
  50
+class PepTest(VirtualenvMixin, BaseScript):
  51
+    config_options = [
  52
+        [["--appname"],
  53
+        {"action": "store",
  54
+         "dest": "appname",
  55
+         "default": None,
  56
+         "help": "Path to the binary (file path or URL) to run the tests on",
  57
+        }],
  58
+        [["--test-manifest"],
  59
+        {"action":"store",
  60
+         "dest": "test_manifest",
  61
+         "default":None,
  62
+         "help": "Path to test manifest to run",
  63
+        }],
  64
+        [["--mozbase-url"],
  65
+        {"action":"store",
  66
+         "dest": "mozbase_url",
  67
+         "default": "https://github.com/mozilla/mozbase/zipball/master",
  68
+         "help": "URL to mozbase zip file",
  69
+        }],
  70
+        [["--peptest-url"],
  71
+        {"action": "store",
  72
+         "dest": "peptest_url",
  73
+         "default": "https://github.com/mozilla/peptest/zipball/master",
  74
+         "help": "URL to peptest zip file",
  75
+        }],
  76
+        [["--test-url"],
  77
+        {"action":"store",
  78
+         "dest": "test_url",
  79
+         "default": None,
  80
+         "help": "URL to the zip file containing the actual tests",
  81
+        }]] + virtualenv_config_options
  82
+
  83
+    error_list = [
  84
+        {'substr': r'''PEP TEST-UNEXPECTED-FAIL''', 'level': ERROR},
  85
+        {'substr': r'''PEP ERROR''', 'level': ERROR},
  86
+        {'substr': r'''PEP WARNING''', 'level': WARNING},
  87
+        {'substr': r'''PEP DEBUG''', 'level': DEBUG},
  88
+    ]
  89
+
  90
+    def __init__(self, require_config_file=False):
  91
+        super(PepTest, self).__init__(
  92
+            config_options=self.config_options,
  93
+            all_actions=['clobber',
  94
+                         'create-deps',
  95
+                         'get-latest-tinderbox',
  96
+                         'run-peptest'],
  97
+            default_actions=['run-peptest'],
  98
+            require_config_file=require_config_file,
  99
+            config={'dependencies': ['mozlog',
  100
+                                     'mozinfo',
  101
+                                     'mozhttpd',
  102
+                                     'manifestdestiny',
  103
+                                     'mozprofile',
  104
+                                     'mozprocess',
  105
+                                     'mozrunner']})
  106
+        # these are necessary since self.config is read only
  107
+        self.appname = self.config.get('appname')
  108
+        self.symbols = self.config.get('symbols_path')
  109
+        self.test_path = self.config.get('test_manifest')
  110
+
  111
+    def create_deps(self):
  112
+        """
  113
+        Create virtualenv and install dependencies
  114
+        """
  115
+        self.create_virtualenv()
  116
+        self._install_deps()
  117
+        self._install_peptest()
  118
+
  119
+    def _install_deps(self):
  120
+        """
  121
+        Download and install dependencies
  122
+        """
  123
+        # download and extract mozbase
  124
+        work_dir = self.query_abs_dirs()['abs_work_dir']
  125
+
  126
+        mozbase = self.config.get('mozbase_path');
  127
+        if not mozbase:
  128
+            self.fatal("No path to mozbase specified. Aborting")
  129
+
  130
+        if self._is_url(mozbase):
  131
+            mozbase = self.download_file(mozbase,
  132
+                      file_name=os.path.join(work_dir, 'mozbase'),
  133
+                      error_level=FATAL)
  134
+
  135
+        if os.path.isfile(mozbase):
  136
+            mozbase = self.extract(mozbase, delete=True, error_level=FATAL)[0]
  137
+
  138
+        python = self.query_python_path()
  139
+        # install dependencies
  140
+        for module in self.config['dependencies']:
  141
+            self.run_command(python + " setup.py install",
  142
+                             cwd=os.path.join(mozbase, module),
  143
+                             error_list=PythonErrorList)
  144
+        self.rmtree(mozbase)
  145
+
  146
+    def _install_peptest(self):
  147
+        """
  148
+        Download and install peptest
  149
+        """
  150
+        # download and extract peptest
  151
+        work_dir = self.query_abs_dirs()['abs_work_dir']
  152
+
  153
+        peptest = self.config.get('peptest_path')
  154
+        if not peptest:
  155
+            self.fatal("No path to peptest specified. Aborting")
  156
+
  157
+        if self._is_url(peptest):
  158
+            peptest = self.download_file(peptest,
  159
+                      file_name=os.path.join(work_dir, 'peptest'),
  160
+                      error_level=FATAL)
  161
+
  162
+        if os.path.isfile(peptest):
  163
+            peptest = self.extract(peptest, delete=True, error_level=FATAL)[0]
  164
+
  165
+        python = self.query_python_path()
  166
+        self.run_command(python + " setup.py install",
  167
+                         cwd=peptest,
  168
+                         error_list=PythonErrorList)
  169
+        self.rmtree(peptest)
  170
+
  171
+    def clobber(self):
  172
+        """
  173
+        Delete the working directory
  174
+        """
  175
+        dirs = self.query_abs_dirs()
  176
+        self.rmtree(dirs['abs_work_dir'])
  177
+
  178
+    def get_latest_tinderbox(self):
  179
+        """
  180
+        Find the url to the latest-tinderbox build and
  181
+        point the appname at it
  182
+        """
  183
+        if not self.query_python_path():
  184
+            self.create_virtualenv()
  185
+        dirs = self.query_abs_dirs()
  186
+
  187
+        if len(self.query_package('getlatesttinderbox')) == 0:
  188
+            # install getlatest-tinderbox
  189
+            self.info("Installing getlatest-tinderbox")
  190
+            pip = self.query_python_path("pip")
  191
+            if not pip:
  192
+                self.error("No application named 'pip' installed")
  193
+            self.run_command(pip + " install GetLatestTinderbox",
  194
+                             cwd=dirs['abs_work_dir'],
  195
+                             error_list=PythonErrorList)
  196
+
  197
+        # get latest tinderbox build url
  198
+        getlatest = self.query_python_path("get-latest-tinderbox")
  199
+        cmd = [getlatest, '--latest']
  200
+        cmd.extend(self._build_arg('--product',
  201
+                   self.config.get('get_latest_tinderbox_product')))
  202
+        cmd.extend(self._build_arg('--platform',
  203
+                   self.config.get('get_latest_tinderbox_platform')))
  204
+        if self.config.get('get_latest_tinderbox_debug_build'):
  205
+            cmd.append('--debug')
  206
+        url = self.get_output_from_command(cmd)
  207
+
  208
+        # get the symbols url to use for debugging crashes
  209
+        cmd = [getlatest, '--url', url, '--symbols']
  210
+        self.symbols = self.get_output_from_command(cmd)
  211
+
  212
+        # get the application url to download and install
  213
+        cmd = [getlatest, '--url', url]
  214
+        self.appname = self.get_output_from_command(cmd)
  215
+
  216
+
  217
+    def preflight_run_peptest(self):
  218
+        if not self.config.get('test_manifest'):
  219
+            self.fatal("No test manifest specified. Aborting")
  220
+
  221
+        if self.config.get('test_url'):
  222
+            bundle = self.download_file(self.config['test_url'])
  223
+            files = self.extract(bundle,
  224
+                                  extdir=self.config.get('test_install_dir'),
  225
+                                  delete=True)
  226
+            self.test_path = os.path.join(files[0],
  227
+                                          self.config['test_manifest'])
  228
+
  229
+        if not os.path.isfile(self.test_path):
  230
+            self.fatal("Test manifest does not exist. Aborting")
  231
+
  232
+        if "create-deps" not in self.actions:
  233
+            # ensure all the dependencies are installed
  234
+            for module in self.config['dependencies'] + ['peptest']:
  235
+                if len(self.query_package(module)) == 0:
  236
+                    self.action_message("Dependencies missing, " +
  237
+                                        "running create-deps step")
  238
+                    self.create_deps()
  239
+                    break
  240
+
  241
+        if not self.appname:
  242
+            self.action_message("No appname specified, " +
  243
+                                "running get-latest-tinderbox step")
  244
+            self.get_latest_tinderbox()
  245
+
  246
+
  247
+    def run_peptest(self):
  248
+        """
  249
+        Run the peptests
  250
+        """
  251
+        if self._is_url(self.appname):
  252
+            self.appname = self._install_from_url(self.appname,
  253
+                                                  error_level=FATAL)
  254
+
  255
+        error_list = self.error_list
  256
+        error_list.extend(PythonErrorList)
  257
+
  258
+        # build the peptest command arguments
  259
+        peptest = self.query_python_path('peptest')
  260
+        cmd = [peptest]
  261
+        cmd.extend(self._build_arg('--app', self.config.get('app')))
  262
+        cmd.extend(self._build_arg('--binary', self.appname))
  263
+        cmd.extend(self._build_arg('--test-path', self.test_path))
  264
+        cmd.extend(self._build_arg('--profile-path',
  265
+                   self.config.get('profile_path')))
  266
+        cmd.extend(self._build_arg('--timeout', self.config.get('timeout')))
  267
+        cmd.extend(self._build_arg('--server-path',
  268
+                   self.config.get('server_path')))
  269
+        cmd.extend(self._build_arg('--server-port',
  270
+                   self.config.get('server_port')))
  271
+        cmd.extend(self._build_arg('--tracer-threshold',
  272
+                   self.config.get('tracer_threshold')))
  273
+        cmd.extend(self._build_arg('--tracer-interval',
  274
+                   self.config.get('tracer_interval')))
  275
+        cmd.extend(self._build_arg('--symbols-path', self.symbols))
  276
+        if (self.config.get('log_level') in
  277
+                           ['debug', 'info', 'warning', 'error']):
  278
+            cmd.extend(['--log-level', self.config['log_level'].upper()])
  279
+
  280
+        code = self.run_command(cmd,
  281
+                                error_list=error_list)
  282
+        # get status and set summary
  283
+        level = ERROR
  284
+        if code == 0:
  285
+            status = "success"
  286
+            level = INFO
  287
+        elif code == 1:
  288
+            status = "test failures"
  289
+        else:
  290
+            status = "harness failure"
  291
+
  292
+        # TODO create a better summary for peptest
  293
+        #      for now just display return code
  294
+        self.add_summary("%s exited with return code %s: %s" % (cmd[0],
  295
+                                                                code,
  296
+                                                                status))
  297
+
  298
+    def _build_arg(self, option, value):
  299
+        """
  300
+        Build a command line argument
  301
+        """
  302
+        if not value:
  303
+            return []
  304
+        return [str(option), str(value)]
  305
+
  306
+    def _install_from_url(self, url, error_level=ERROR):
  307
+        """
  308
+        Accepts a URL to the application (usually on ftp.m.o)
  309
+        Downloads and installs the application
  310
+        Returns the binary path
  311
+        """
  312
+        dirs = self.query_abs_dirs()
  313
+        # ensure mozinstall is available
  314
+        if len(self.query_package("mozinstall")) == 0:
  315
+            # install mozinstall
  316
+            self.info("Installing mozinstall")
  317
+            pip = self.query_python_path("pip")
  318
+            if not pip:
  319
+                self.log("No application named 'pip' installed",
  320
+                         level=error_level)
  321
+            self.run_command(pip + " install mozInstall",
  322
+                             cwd=dirs['abs_work_dir'],
  323
+                             error_list=PythonErrorList)
  324
+
  325
+        # download the application
  326
+        source = os.path.realpath(self.download_file(url))
  327
+
  328
+        # install the application
  329
+        mozinstall = self.query_python_path("mozinstall")
  330
+        cmd = [mozinstall, '--source', source]
  331
+        cmd.extend(self._build_arg('--destination',
  332
+                   self.config.get('application_install_dir')))
  333
+        binary = self.get_output_from_command(cmd)
  334
+
  335
+        # cleanup
  336
+        self.rmtree(source)
  337
+        return binary
  338
+
  339
+    def _is_url(self, path):
  340
+        """
  341
+        Return True if path looks like a URL.
  342
+        """
  343
+        if path is not None:
  344
+            parsed = urlparse.urlparse(path)
  345
+            return parsed.scheme != '' or parsed.netloc != ''
  346
+        return False
  347
+
  348
+
  349
+
  350
+
  351
+if __name__ == '__main__':
  352
+    peptest = PepTest()
  353
+    peptest.run()

0 notes on commit 4e7318c

Please sign in to comment.
Something went wrong with that request. Please try again.