Source code for webdriverplus

from selenium.webdriver import DesiredCapabilities
from selenium.webdriver.firefox.webdriver import WebDriver as _Firefox
from selenium.webdriver.chrome.webdriver import WebDriver as _Chrome
from selenium.webdriver.ie.webdriver import WebDriver as _Ie
from selenium.webdriver.remote.webdriver import WebDriver as _Remote
from selenium.webdriver.phantomjs.webdriver import WebDriver as _PhantomJS

from webdriverplus.utils import _download
from webdriverplus.webdriver import WebDriverDecorator
from webdriverplus.webelement import WebElement

import atexit
import os
import socket
import subprocess
import time

try:
    from urllib2 import URLError
except ImportError:
    from urllib.error import URLError

VERSION = (0, 2, 0)


def get_version():
    return '%d.%d.%d' % (VERSION[0], VERSION[1], VERSION[2])


[docs]class WebDriver(WebDriverDecorator): _pool = {} # name -> (instance, signature) _quit_on_exit = set() # set of instances _selenium_server = None # Popen object _default_browser_name = 'firefox' @classmethod def _at_exit(cls): """ Gets registered to run on system exit. """ if cls._selenium_server: cls._selenium_server.kill() for driver in cls._quit_on_exit: try: driver.quit(force=True) except URLError: pass @classmethod def _clear(cls): cls._pool.clear() @classmethod def _get_from_pool(cls, browser): """Returns (instance, (args, kwargs))""" return cls._pool.get(browser, (None, (None, None))) def __new__(cls, browser=None, *args, **kwargs): quit_on_exit = kwargs.get('quit_on_exit', True) reuse_browser = kwargs.get('reuse_browser') signature = (args, kwargs) browser = browser or cls._default_browser_name reused_pooled_browser = False pooled_browser = None try: is_str = isinstance(browser, basestring) except NameError: is_str = isinstance(browser, str) if is_str: browser = browser.lower() pooled_browser, pooled_signature = WebDriver._get_from_pool(browser) if pooled_signature == signature: driver = pooled_browser reused_pooled_browser = True elif browser == 'firefox': driver = Firefox(*args, **kwargs) elif browser == 'chrome': driver = Chrome(*args, **kwargs) elif browser == 'ie': driver = Ie(*args, **kwargs) elif browser == 'remote': driver = Remote(*args, **kwargs) elif browser == 'phantomjs': driver = PhantomJS(*args, **kwargs) elif browser == 'htmlunit': driver = HtmlUnit(*args, **kwargs) # If a WebDriverDecorator/WebDriver is given, add it to the pool elif isinstance(browser, WebDriverDecorator): driver = browser browser = driver.name else: kwargs['driver'] = browser driver = WebDriverDecorator(*args, **kwargs) browser = driver.name if reuse_browser and not reused_pooled_browser: if pooled_browser: pooled_browser.quit(force=True) WebDriver._pool[browser] = (driver, signature) if quit_on_exit: WebDriver._quit_on_exit.add(driver) return driver def __init__(self, browser='firefox', *args, **kwargs): pass
# Not actually called. Here for autodoc purposes only. atexit.register(WebDriver._at_exit) class Firefox(WebDriverDecorator): def __init__(self, *args, **kwargs): kwargs['driver'] = _Firefox super(Firefox, self).__init__(*args, **kwargs) class Chrome(WebDriverDecorator): def __init__(self, *args, **kwargs): kwargs['driver'] = _Chrome super(Chrome, self).__init__(*args, **kwargs) class Ie(WebDriverDecorator): def __init__(self, *args, **kwargs): kwargs['driver'] = _Ie super(Ie, self).__init__(*args, **kwargs) class Remote(WebDriverDecorator): def __init__(self, *args, **kwargs): kwargs['driver'] = _Remote super(Remote, self).__init__(*args, **kwargs) class PhantomJS(WebDriverDecorator): def __init__(self, *args, **kwargs): kwargs['driver'] = _PhantomJS super(PhantomJS, self).__init__(*args, **kwargs) class HtmlUnit(Remote): _selenium = 'selenium-server-standalone-2.33.0.jar' _selenium_url = 'http://selenium.googlecode.com/files/' + _selenium _auto_install = True def __init__(self, *args, **kwargs): self._perform_auto_install() self._autorun_selenium_server() super(HtmlUnit, self).__init__("http://localhost:4444/wd/hub", DesiredCapabilities.HTMLUNIT, **kwargs) def _create_web_element(self, element_id): return HtmlUnitWebElement(self, element_id) def _get_webdriver_dir(self): directory = os.path.expanduser('~/.webdriverplus') if not os.path.exists(directory): os.mkdir(directory) return directory def _get_selenium_path(self): return self._get_webdriver_dir() + '/' + self._selenium def _perform_auto_install(self): if not self._auto_install: return selenium_server = self._get_selenium_path() if not os.path.exists(selenium_server): _download(self._selenium_url, selenium_server) def _autorun_selenium_server(self): if WebDriver._selenium_server: return if subprocess.call(['hash', 'java']) != 0: raise Exception('java does not appear to be installed.') fnull = open(os.devnull, 'w') args = ['java', '-jar', self._get_selenium_path()] WebDriver._selenium_server = subprocess.Popen(args, stdout=fnull, stderr=fnull) now = time.time() timeout = 10 connected = False while time.time() - now < timeout: try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('127.0.0.1', 4444)) except: time.sleep(0.2) else: sock.close() connected = True break if not connected: raise Exception('Could not connect to selenium server') class HtmlUnitWebElement(WebElement): def descendants(self): # HtmlUnit adds self into descendants ret = super(HtmlUnitWebElement, self).descendants() ret.discard(self) return ret @property def inner_html(self): # Need to use JS to do inner_html with HtmlUnit. script = "return arguments[0].innerHTML;" return self._parent.execute_script(script, self)