def __init__(self, remote_server_addr, keep_alive=False): # Attempt to resolve the hostname and get an IP address. self.keep_alive = keep_alive self.error_handler = ErrorHandler() parsed_url = parse.urlparse(remote_server_addr) addr = "" if parsed_url.hostname: try: netloc = socket.gethostbyname(parsed_url.hostname) addr = netloc if parsed_url.port: netloc += ':%d' % parsed_url.port if parsed_url.username: auth = parsed_url.username if parsed_url.password: auth += ':%s' % parsed_url.password netloc = '%s@%s' % (auth, netloc) remote_server_addr = parse.urlunparse( (parsed_url.scheme, netloc, parsed_url.path, parsed_url.params, parsed_url.query, parsed_url.fragment)) except socket.gaierror: LOGGER.info('Could not get IP address for host: %s' % parsed_url.hostname) self._url = remote_server_addr if keep_alive: self._conn = httplib.HTTPConnection( str(addr), str(parsed_url.port), timeout=self._timeout)
def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities=None, browser_profile=None): """Create a new driver that will issue commands using the wire protocol. Args: command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. desired_capabilities - Dictionary holding predefined values for starting a browser browser_profile: A browser profile directory as a Base64-encoded zip file. Only used if Firefox is requested. """ if desired_capabilities is None: raise WebDriverException(" Desired Capabilities can't be None") self.command_executor = command_executor if type(self.command_executor) is str: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(desired_capabilities, browser_profile)
def __init__(self, command_executor, browser_name, platform, version='', javascript_enabled=True): """Create a new driver that will issue commands using the wire protocol. Args: command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. browser_name - A string indicating which browser to request a new session for from the remote server. Should be one of {mobile safari|firefox|internet explorer|htmlunit|chrome}. platform - A string indicating the desired platform to request from the remote server. Should be one of {WINDOWS|XP|VISTA|MAC|LINUX|UNIX|ANY}. version - A string indicating a specific browser version to request, or an empty string ot use any available browser. Defaults to the empty string. javascript_enabled - Whether the requested browser should support JavaScript. Defaults to True. """ self.command_executor = command_executor if type(self.command_executor) is str: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(browser_name=browser_name, platform=platform, version=version, javascript_enabled=javascript_enabled)
def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities=None, browser_profile=None): """ Create a new driver that will issue commands using the wire protocol. :Args: - command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. - desired_capabilities - Dictionary holding predefined values for starting a browser - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. """ if desired_capabilities is None: raise WebDriverException("Desired Capabilities can't be None") if not isinstance(desired_capabilities, dict): raise WebDriverException( "Desired Capabilities must be a dictionary") self.command_executor = command_executor if type(self.command_executor) is str or type( self.command_executor) is unicode: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(desired_capabilities, browser_profile)
def __init__(self, command_executor='http://localhost:4444/wd/hub', desired_capabilities = None, browser_profile=None): """Create a new driver that will issue commands using the wire protocol. Args: command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. desired_capabilities - Dictionary holding predefined values for starting a browser browser_profile: A browser profile directory as a Base64-encoded zip file. Only used if Firefox is requested. """ if desired_capabilities is None: raise WebDriverException(" Desired Capabilities can't be None") self.command_executor = command_executor if type(self.command_executor) is str: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(desired_capabilities, browser_profile)
def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities=None, browser_profile=None, proxy=None): """ Create a new driver that will issue commands using the wire protocol. :Args: - command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. - desired_capabilities - Dictionary holding predefined values for starting a browser - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. """ if desired_capabilities is None: raise WebDriverException("Desired Capabilities can't be None") if not isinstance(desired_capabilities, dict): raise WebDriverException("Desired Capabilities must be a dictionary") if proxy is not None: proxy.add_to_capabilities(desired_capabilities) self.command_executor = command_executor if type(self.command_executor) is str or type(self.command_executor) is unicode: self.command_executor = RemoteConnection(command_executor) self._is_remote = True self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(desired_capabilities, browser_profile)
def _main(arguments): error_tracker = ErrorHandler() run(arguments) if error_tracker.fired: print( "A fatal error occurred, please review the log output for more information.", file=sys.stderr, ) sys.exit(1) sys.exit(0)
def _configure_logging(log_level: str) -> None: logger = logging.getLogger(__name__) logging.basicConfig( handlers=[ logging.StreamHandler(sys.stdout), ], format="%(asctime)s - %(levelname)s - %(name)s - %(message)s", level=log_level, ) error_tracker = ErrorHandler() return logger, error_tracker
async def main() -> None: load_dotenv() configuration = parse_main_arguments() _configure_logging(configuration) # Important that this comes _after_ the logging configuration error_tracker = ErrorHandler() await run(configuration) if error_tracker.fired: print( "A fatal error occurred, please review the log output for more information.", file=sys.stderr, ) sys.exit(1) sys.exit(0)
def main() -> None: load_dotenv() # WARNING! Do not make the following call in a function decorated with @catch_exceptions arguments = parse_main_arguments(sys.argv[1:]) _configure_logging(arguments) error_tracker: ErrorHandler = ErrorHandler() _run_loader(arguments) if error_tracker.fired: print( "A fatal error occurred, please review the log output for more information.", file=sys.stderr, ) sys.exit(1) sys.exit(0)
def main() -> None: global logger load_dotenv() arguments = parse_main_arguments(sys.argv[1:]) _configure_logging(arguments) error_tracker: ErrorHandler = ErrorHandler() try: run(arguments) except Exception as error: logger.error(error) print(error.__traceback__, file=sys.stderr) if error_tracker.fired: print( "A fatal error occurred, please review the log output for more information.", file=sys.stderr, ) sys.exit(1) sys.exit(0)
def __init__(self, bp_name, filename, url_prefix="", template_folder=""): # setting blue print for this module self.set_blueprint(bp_name, filename, url_prefix, template_folder) # == self.error_handle = ErrorHandler() # common - varbiales available to all module templates self.common = {} # == # Required roles, leaving this empty means anyone can access this module. # anon - is the defualt role a(not logged in). # viewer - is the default role of a logged in user. # buyer - Consumer looking for ad spaces, has access to the search module (has already made a payment). # subscriber - A subscribed user # provider - Ad space provider, who will have access to add their media to the system. # admin - Has access to everything self.admin_role = "admin" self.available_roles = [ "anon", "viewer", "buyer", "subscriber", "provider", self.admin_role ] self.required_roles = [] # set in each module
class WebDriver(object): """ Controls a browser by sending commands to a remote server. This server is expected to be running the WebDriver wire protocol as defined here: http://code.google.com/p/selenium/wiki/JsonWireProtocol :Attributes: - command_executor - The command.CommandExecutor object used to execute commands. - error_handler - errorhandler.ErrorHandler object used to verify that the server did not return an error. - session_id - The session ID to send with every command. - capabilities - A dictionary of capabilities of the underlying browser for this instance's session. """ def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities=None, browser_profile=None): """ Create a new driver that will issue commands using the wire protocol. :Args: - command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. - desired_capabilities - Dictionary holding predefined values for starting a browser - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. """ if desired_capabilities is None: raise WebDriverException("Desired Capabilities can't be None") if not isinstance(desired_capabilities, dict): raise WebDriverException( "Desired Capabilities must be a dictionary") self.command_executor = command_executor if type(self.command_executor) is str or type( self.command_executor) is unicode: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(desired_capabilities, browser_profile) @property def name(self): """Returns the name of the underlying browser for this instance. :Usage: - driver.name """ if 'browserName' in self.capabilities: return self.capabilities['browserName'] else: raise KeyError('browserName not specified in session capabilities') def start_client(self): """ Called before starting a new session. This method may be overridden to define custom startup behavior. """ pass def stop_client(self): """ Called after executing a quit command. This method may be overridden to define custom shutdown behavior. """ pass def start_session(self, desired_capabilities, browser_profile=None): """ Creates a new session with the desired capabilities. :Args: - browser_name - The name of the browser to request. - version - Which browser version to request. - platform - Which platform to request the browser on. - javascript_enabled - Whether the new session should support JavaScript. - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. """ if browser_profile: desired_capabilities['firefox_profile'] = browser_profile.encoded response = self.execute(Command.NEW_SESSION, { 'desiredCapabilities': desired_capabilities, }) self.session_id = response['sessionId'] self.capabilities = response['value'] def _wrap_value(self, value): if isinstance(value, dict): converted = {} for key, val in value.items(): converted[key] = self._wrap_value(val) return converted elif isinstance(value, WebElement): return {'ELEMENT': value.id} elif isinstance(value, list): return list(self._wrap_value(item) for item in value) else: return value def create_web_element(self, element_id): """ Creates a web element with the specified element_id. """ return WebElement(self, element_id) def _unwrap_value(self, value): if isinstance(value, dict) and 'ELEMENT' in value: return self.create_web_element(value['ELEMENT']) elif isinstance(value, list): return list(self._unwrap_value(item) for item in value) else: return value def execute(self, driver_command, params=None): """ Sends a command to be executed by a command.CommandExecutor. :Args: - driver_command: The name of the command to execute as a string. - params: A dictionary of named parameters to send with the command. :Returns: The command's JSON response loaded into a dictionary object. """ if not params: params = {'sessionId': self.session_id} elif 'sessionId' not in params: params['sessionId'] = self.session_id params = self._wrap_value(params) response = self.command_executor.execute(driver_command, params) if response: self.error_handler.check_response(response) response['value'] = self._unwrap_value(response.get('value', None)) return response # If the server doesn't send a response, assume the command was # a success return {'success': 0, 'value': None, 'sessionId': self.session_id} def get(self, url): """ Loads a web page in the current browser session. """ self.execute(Command.GET, {'url': url}) @property def title(self): """Returns the title of the current page. :Usage: driver.title """ resp = self.execute(Command.GET_TITLE) return resp['value'] if resp['value'] is not None else "" def find_element_by_id(self, id_): """Finds an element by id. :Args: - id\_ - The id of the element to be found. :Usage: driver.find_element_by_id('foo') """ return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_): """ Finds multiple elements by id. :Args: - id\_ - The id of the elements to be found. :Usage: driver.find_element_by_id('foo') """ return self.find_elements(by=By.ID, value=id_) def find_element_by_xpath(self, xpath): """ Finds an element by xpath. :Args: - xpath - The xpath locator of the element to find. :Usage: driver.find_element_by_xpath('//div/td[1]') """ return self.find_element(by=By.XPATH, value=xpath) def find_elements_by_xpath(self, xpath): """ Finds multiple elements by xpath. :Args: - xpath - The xpath locator of the elements to be found. :Usage: driver.find_elements_by_xpath("//div[contains(@class, 'foo')]") """ return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_link_text(self, link_text): """ Finds an element by link text. :Args: - link_text: The text of the element to be found. :Usage: driver.find_element_by_link_text('Sign In') """ return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, text): """ Finds elements by link text. :Args: - link_text: The text of the elements to be found. :Usage: driver.find_elements_by_link_text('Sign In') """ return self.find_elements(by=By.LINK_TEXT, value=text) def find_element_by_partial_link_text(self, link_text): """ Finds an element by a partial match of its link text. :Args: - link_text: The text of the element to partially match on. :Usage: driver.find_element_by_partial_link_text('Sign') """ return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text): """ Finds elements by a partial match of their link text. :Args: - link_text: The text of the element to partial match on. :Usage: driver.find_element_by_partial_link_text('Sign') """ return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_name(self, name): """ Finds an element by name. :Args: - name: The name of the element to find. :Usage: driver.find_element_by_name('foo') """ return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name): """ Finds elements by name. :Args: - name: The name of the elements to find. :Usage: driver.find_elements_by_name('foo') """ return self.find_elements(by=By.NAME, value=name) def find_element_by_tag_name(self, name): """ Finds an element by tag name. :Args: - name: The tag name of the element to find. :Usage: driver.find_element_by_tag_name('foo') """ return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name): """ Finds elements by tag name. :Args: - name: The tag name the use when finding elements. :Usage: driver.find_elements_by_tag_name('foo') """ return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_class_name(self, name): """ Finds an element by class name. :Args: - name: The class name of the element to find. :Usage: driver.find_element_by_class_name('foo') """ return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name): """ Finds elements by class name. :Args: - name: The class name of the elements to find. :Usage: driver.find_elements_by_class_name('foo') """ return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector): """ Finds an element by css selector. :Args: - css_selector: The css selector to use when finding elements. :Usage: driver.find_element_by_css_selector('#foo') """ return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector): """ Finds elements by css selector. :Args: - css_selector: The css selector to use when finding elements. :Usage: driver.find_element_by_css_selector('#foo') """ return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def execute_script(self, script, *args): """ Synchronously Executes JavaScript in the current window/frame. :Args: - script: The JavaScript to execute. - \*args: Any applicable arguments for your JavaScript. :Usage: driver.execute_script('document.title') """ if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute(Command.EXECUTE_SCRIPT, { 'script': script, 'args': converted_args })['value'] def execute_async_script(self, script, *args): """ Asynchronously Executes JavaScript in the current window/frame. :Args: - script: The JavaScript to execute. - \*args: Any applicable arguments for your JavaScript. :Usage: driver.execute_async_script('document.title') """ if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute(Command.EXECUTE_ASYNC_SCRIPT, { 'script': script, 'args': converted_args })['value'] @property def current_url(self): """ Gets the URL of the current page. :Usage: driver.current_url """ return self.execute(Command.GET_CURRENT_URL)['value'] @property def page_source(self): """ Gets the source of the current page. :Usage: driver.page_source """ return self.execute(Command.GET_PAGE_SOURCE)['value'] def close(self): """ Closes the current window. :Usage: driver.close() """ self.execute(Command.CLOSE) def quit(self): """ Quits the driver and closes every associated window. :Usage: driver.quit() """ try: self.execute(Command.QUIT) finally: self.stop_client() @property def current_window_handle(self): """ Returns the handle of the current window. :Usage: driver.current_window_handle """ return self.execute(Command.GET_CURRENT_WINDOW_HANDLE)['value'] @property def window_handles(self): """ Returns the handles of all windows within the current session. :Usage: driver.window_handles """ return self.execute(Command.GET_WINDOW_HANDLES)['value'] def maximize_window(self): """ Maximizes the current window that webdriver is using """ self.execute(Command.MAXIMIZE_WINDOW, {"windowHandle": "current"}) #Target Locators def switch_to_active_element(self): """ Returns the element with focus, or BODY if nothing has focus. :Usage: driver.switch_to_active_element() """ return self.execute(Command.GET_ACTIVE_ELEMENT)['value'] def switch_to_window(self, window_name): """ Switches focus to the specified window. :Args: - window_name: The name or window handle of the window to switch to. :Usage: driver.switch_to_window('main') """ self.execute(Command.SWITCH_TO_WINDOW, {'name': window_name}) def switch_to_frame(self, frame_reference): """ Switches focus to the specified frame, by index, name, or webelement. :Args: - frame_reference: The name of the window to switch to, an integer representing the index, or a webelement that is an (i)frame to switch to. :Usage: driver.switch_to_frame('frame_name') driver.switch_to_frame(1) driver.switch_to_frame(driver.find_elements_by_tag_name("iframe")[0]) """ self.execute(Command.SWITCH_TO_FRAME, {'id': frame_reference}) def switch_to_default_content(self): """ Switch focus to the default frame. :Usage: driver.switch_to_default_content() """ self.execute(Command.SWITCH_TO_FRAME, {'id': None}) def switch_to_alert(self): """ Switches focus to an alert on the page. :Usage: driver.switch_to_alert() """ return Alert(self) #Navigation def back(self): """ Goes one step backward in the browser history. :Usage: driver.back() """ self.execute(Command.GO_BACK) def forward(self): """ Goes one step forward in the browser history. :Usage: driver.forward() """ self.execute(Command.GO_FORWARD) def refresh(self): """ Refreshes the current page. :Usage: driver.refresh() """ self.execute(Command.REFRESH) # Options def get_cookies(self): """ Returns a set of dictionaries, corresponding to cookies visible in the current session. :Usage: driver.get_cookies() """ return self.execute(Command.GET_ALL_COOKIES)['value'] def get_cookie(self, name): """ Get a single cookie by name. Returns the cookie if found, None if not. :Usage: driver.get_cookie('my_cookie') """ cookies = self.get_cookies() for cookie in cookies: if cookie['name'] == name: return cookie return None def delete_cookie(self, name): """ Deletes a single cookie with the given name. :Usage: driver.delete_cookie('my_cookie') """ self.execute(Command.DELETE_COOKIE, {'name': name}) def delete_all_cookies(self): """ Delete all cookies in the scope of the session. :Usage: driver.delete_all_cookies() """ self.execute(Command.DELETE_ALL_COOKIES) def add_cookie(self, cookie_dict): """ Adds a cookie to your current session. :Args: - cookie_dict: A dictionary object, with required keys - "name" and "value"; optional keys - "path", "domain", "secure", "expiry" Usage: driver.add_cookie({'name' : 'foo', 'value' : 'bar'}) driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/'}) driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/', 'secure':True}) """ self.execute(Command.ADD_COOKIE, {'cookie': cookie_dict}) # Timeouts def implicitly_wait(self, time_to_wait): """ Sets a sticky timeout to implicitly wait for an element to be found, or a command to complete. This method only needs to be called one time per session. To set the timeout for calls to execute_async_script, see set_script_timeout. :Args: - time_to_wait: Amount of time to wait (in seconds) :Usage: driver.implicitly_wait(30) """ self.execute(Command.IMPLICIT_WAIT, {'ms': float(time_to_wait) * 1000}) def set_script_timeout(self, time_to_wait): """ Set the amount of time that the script should wait during an execute_async_script call before throwing an error. :Args: - time_to_wait: The amount of time to wait :Usage: driver.set_script_timeout(30) """ self.execute(Command.SET_SCRIPT_TIMEOUT, {'ms': float(time_to_wait) * 1000}) def set_page_load_timeout(self, time_to_wait): """ Set the amount of time to wait for a page load to complete before throwing an error. :Args: - time_to_wait: The amount of time to wait :Usage: driver.set_page_load_timeout(30) """ self.execute(Command.SET_TIMEOUTS, { 'ms': float(time_to_wait) * 1000, 'type': 'page load' }) def find_element(self, by=By.ID, value=None): """ 'Private' method used by the find_element_by_* methods. :Usage: Use the corresponding find_element_by_* instead of this. """ if isinstance(by, tuple) or isinstance(value, int) or value == None: raise InvalidSelectorException("Invalid locator values passed in") return self.execute(Command.FIND_ELEMENT, { 'using': by, 'value': value })['value'] def find_elements(self, by=By.ID, value=None): """ 'Private' method used by the find_elements_by_* methods. :Usage: Use the corresponding find_elements_by_* instead of this. """ if isinstance(by, tuple) or isinstance(value, int) or value == None: raise InvalidSelectorException("Invalid locator values passed in") return self.execute(Command.FIND_ELEMENTS, { 'using': by, 'value': value })['value'] @property def desired_capabilities(self): """ returns the drivers current desired capabilities being used """ return self.capabilities def get_screenshot_as_file(self, filename): """ Gets the screenshot of the current window. Returns False if there is any IOError, else returns True. Use full paths in your filename. :Args: - filename: The full path you wish to save your screenshot to. :Usage: driver.get_screenshot_as_file('/Screenshots/foo.png') """ png = self.execute(Command.SCREENSHOT)['value'] try: with open(filename, 'wb') as f: f.write(base64.decodestring(png)) except IOError: return False del png return True def get_screenshot_as_base64(self): """ Gets the screenshot of the current window as a base64 encoded string which is useful in embedded images in HTML. :Usage: driver.get_screenshot_as_base64() """ return self.execute(Command.SCREENSHOT)['value'] def set_window_size(self, width, height, windowHandle='current'): """ Sets the width and height of the current window. (window.resizeTo) :Args: - width: the width in pixels to set the window to - height: the height in pixels to set the window to :Usage: driver.set_window_size(800,600) """ self.execute(Command.SET_WINDOW_SIZE, { 'width': width, 'height': height, 'windowHandle': windowHandle }) def get_window_size(self, windowHandle='current'): """ Gets the width and height of the current window. :Usage: driver.get_window_size() """ return self.execute(Command.GET_WINDOW_SIZE, {'windowHandle': windowHandle})['value'] def set_window_position(self, x, y, windowHandle='current'): """ Sets the x,y position of the current window. (window.moveTo) :Args: - x: the x-coordinate in pixels to set the window position - y: the y-coordinate in pixels to set the window position :Usage: driver.set_window_position(0,0) """ self.execute(Command.SET_WINDOW_POSITION, { 'x': x, 'y': y, 'windowHandle': windowHandle }) def get_window_position(self, windowHandle='current'): """ Gets the x,y position of the current window. :Usage: driver.get_window_position() """ return self.execute(Command.GET_WINDOW_POSITION, {'windowHandle': windowHandle})['value'] @property def orientation(self): """ Gets the current orientation of the device :Usage: orientation = driver.orientation """ return self.execute(Command.GET_SCREEN_ORIENTATION)['value'] @orientation.setter def orientation(self, value): """ Sets the current orientation of the device :Args: - value: orientation to set it to. :Usage: driver.orientation = 'landscape' """ allowed_values = ['LANDSCAPE', 'PORTRAIT'] if value.upper() in allowed_values: self.execute(Command.SET_SCREEN_ORIENTATION, {'orientation': value})['value'] else: raise WebDriverException( "You can only set the orientation to 'LANDSCAPE' and 'PORTRAIT'" ) def is_online(self): """ Returns a boolean if the browser is online or offline""" return self.execute(Command.IS_BROWSER_ONLINE)['value'] @property def application_cache(self): """ Returns a ApplicationCache Object to interact with the browser app cache""" return ApplicationCache(self)
class Controller(object): """ Parent class to all Controller classes. """ def __init__(self): self.error_handle = ErrorHandler() self.cache_handle = Cache def get_db_handler(self): """ Returns the DB handler """ mc = MongoClient() return mc[current_app.config["DB"]["name"]] def add_db_item(self, collection=None, content=None, _id=None, upsert=False): """ Save an item to the DB """ try: if collection and content: db = self.get_db_handler() _id = db[collection].save(content) return {"status": "success", "message": "Successfully added item to the DB", "_id": _id} return None except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.controller.add_db_item()") def update_db_item(self, collection=None, conditions=None, content=None, upsert=False, overwrite=False, noobjectify=False, multi=False): """ Update/upsert a DB item """ try: if collection and conditions and content: db = self.get_db_handler() if noobjectify==False and "_id" in conditions: conditions["_id"] = ObjectId(conditions["_id"]) if overwrite: db[collection].update(conditions, {"$set": content}, upsert=upsert, multi=multi) else: db[collection].update(conditions, content, upsert=upsert, multi=multi) return {"status": "success", "message": "DB item updated successfully."} except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.controller.update_db_item()") def get_db_items(self, collection=None, conditions=None, sort_by=[("_id", 1)]): """ Get items from a collection in the DB and return results """ try: if collection: if conditions and "_id" in conditions: # By default, if an _id is provided, it'll be converted into an ObjectId instance. # "noobjectify" would prevent it from making use of the _id directly instead of # converting it into an ObjectId instance. if not "noobjectify" in conditions or conditions["noobjectify"]==False: conditions.update({"_id": ObjectId(conditions["_id"])}) items = self.get_db_handler()[collection].find(conditions).sort(sort_by) if items: return items return None except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.controller.get_db_items()") def get_db_distinct_items(self, collection=None, fieldname=None, conditions=None, sort_by=[("_id", 1)]): """ Get unique/distinct values from all records of the given field """ try: if collection and fieldname: return self.get_db_handler()[collection].find(conditions).sort(sort_by).distinct(fieldname) return None except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.controller.get_db_distinct_items()") def remove_db_item(self, collection=None, conditions=None, remove_all=False): """ Remove an or all items from the collection, based on given conditions """ try: if remove_all: conditions = {} if collection and conditions: self.get_db_handler()[collection].remove(conditions) return {"status": "success", "message": "Successfully removed item(s) from the DB"} except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.controller.remove_db_item()")
class Model(object): """ Base class to all Models """ def __init__(self): self.db_name = current_app.config["DB"]["name"] self.collection_name = "" self.content = None self.error_handle = ErrorHandler() def set_content(self): """ There should be a definition of this function in every child class. This function prepares a dictionary of the child class object's parameters which are to be saved, and set it to self.content """ pass def set_objprops(self, data=None): """ This function should have a definition in a child class for when a single result is expected from the DB query. (when findone=True). Eg: When fetching a user from the DB. This function should then populate the appropriate properties of the object with the data fetched from the DB """ pass def get_db_handler(self): """ Return DB handler for the appropriate collection, returns None if no collection name provided """ if not self.collection_name == "": return MongoClient()[self.db_name][self.collection_name] else: return None def check_duplicate(self, fields): """ provided fields, this function will return true if there is a duplicate entry false if no duplicate value found eg: fields = {"name": "John", "age": 20} """ try: dbh = self.get_db_handler() if dbh.find(fields).count() > 0: return True return False except Exception as e: return self.error_handle.get_error( error=str(e), occurred_at="mad.lib.Model.check_duplicate()") def get(self, conditions=None, sort_by=[("_id", 1)], distinct=False, distinct_fieldname=None, limit=0, findone=False): """ Return db items fullfilled by conditions, and sorted by ID """ try: dbh = self.get_db_handler() content = None if conditions and "_id" in conditions: if not "noobjectify" in conditions or conditions[ "noobjectify"] == False: conditions.update({"_id": ObjectId(conditions["_id"])}) if "noobjectify" in conditions: del conditions["noobjectify"] if distinct == True and distinct_fieldname: content = dbh.find(conditions).sort(sort_by).distinct( distinct_fieldname) elif findone == True: content = dbh.find_one(conditions) else: content = dbh.find(conditions).sort(sort_by) if content and limit > 0: content = content.limit(limit) return content except Exception as e: return self.error_handle.get_error( error=str(e), occurred_at="mad.lib.Model.get()") def save(self, duplicate_fields_check=None, allow_duplicate=False): """ Add a new item to the collection """ try: # duplicate_fields_check should be a dict, with field and its corresponding value self.set_content() if not self.content == None: if allow_duplicate == False and not duplicate_fields_check == None: if self.check_duplicate( fields=duplicate_fields_check) == True: return { "status": "failed", "message": "Could not save item. Duplicate entry found." } dbh = self.get_db_handler() dbh.save(self.content) return { "status": "success", "message": "Successfully added item to the DB" } return {"status": "failed", "message": "Content is empty"} except Exception as e: return self.error_handle.get_error( error=str(e), occurred_at="mad.lib.Model.save()") def update(self, conditions={}, overwrite=False, upsert=False, noobjectify=False, multi=False): """ Update a DB entry """ try: self.set_content() dbh = self.get_db_handler() if "_id" in conditions or "_id" in self.content: if not "noobjectify" in conditions or conditions[ "noobjectify"] == False: if not "_id" in conditions: conditions.update( {"_id": ObjectId(self.content["_id"])}) del self.content["_id"] else: conditions.update({"_id": ObjectId(conditions["_id"])}) #remove "noobjectify" from conditions, since it should not be used in update query if "noobjectify" in conditions: del conditions["noobjectify"] if overwrite: dbh.update(conditions, self.content, upsert=upsert, multi=multi) else: dbh.update(conditions, {"$set": self.content}, upsert=upsert, multi=multi) return { "status": "success", "message": "DB item updated successfully." } except Exception as e: return self.error_handle.get_error( error=str(e), occurred_at="mad.lib.Model.update()") def remove(self, conditions=None, remove_all=False): """ Remove 1 or more items from the collection """ try: if remove_all == True: conditions = {} elif not conditions == None: if "_id" in conditions: if not "noobjectify" in conditions or conditions[ "noobjectify"] == False: conditions.update({"_id": ObjectId(conditions["_id"])}) #remove "noobjectify" from conditions, since it should not be used in update query if "noobjectify" in conditions: del conditions["noobjectify"] self.get_db_handler().remove(conditions) return { "status": "success", "message": "Successfully removed item(s) from the DB" } except Exception as e: return self.error_handle.get_error( error=str(e), occurred_at="mad.lib.Model.remove()")
def __init__(self): self.error_handle = ErrorHandler() self.cache_handle = Cache
def __init__(self): self.db_name = current_app.config["DB"]["name"] self.collection_name = "" self.content = None self.error_handle = ErrorHandler()
class ErrorFilter(BaseReader, BaseWriter): temp_path = None def __init__(self, level=logging.ERROR, message="No output as errors have occurred."): from errorhandler import ErrorHandler self.handler = ErrorHandler(level) self.message = message def start(self, create=True): self.prefix = 0 self.handler.reset() if self.temp_path is not None: rmtree(self.temp_path) if create: self.temp_path = mkdtemp() else: self.temp_path = None BaseWriter.start(self) def get_stream(self, filename): self.prefix += 1 return open(os.path.join(self.temp_path, str(self.prefix) + "-" + filename), "wb") def get_workbooks(self): if self.temp_path is None: return filenames = [] for name in os.listdir(self.temp_path): d = name.split("-", 1) d.append(name) filenames.append(d) filenames.sort() for i, filename, pathname in filenames: yield ( # We currently don't open with on_demand=True here # as error filters should be lastish in the chain # so there's not much win. # However, if we did, getting rid of the temp dirs # becomes a problem as, on Windows, they can't be # deleted until the xlrd.Book object is done with # and we don't know when that might be :-( xlrd.open_workbook( os.path.join(self.temp_path, pathname), pickleable=0, formatting_info=1, on_demand=False, ragged_rows=True, ), filename, ) def sheet(self, rdsheet, wtsheet_name): self.rdsheet = rdsheet BaseWriter.sheet(self, rdsheet, wtsheet_name) def cell(self, rdrowx, rdcolx, wtrowx, wtcolx): cell = self.rdsheet.cell(rdrowx, rdcolx) if cell.ctype == xlrd.XL_CELL_EMPTY: return if cell.ctype == xlrd.XL_CELL_ERROR: logger.error( "Cell %s of sheet %r contains a bad value: %s" % ( xlrd.cellname(rdrowx, rdcolx), quoted_sheet_name(self.rdsheet.name), cell_display(cell, self.rdbook.datemode), ) ) return BaseWriter.cell(self, rdrowx, rdcolx, wtrowx, wtcolx) def finish(self): BaseWriter.finish(self) if self.handler.fired: logger.error(self.message) else: self(self.next) self.start(create=False) for attr in ("rdbook", "rdsheet"): if hasattr(self, attr): delattr(self, attr)
class WebDriver(object): """Controls a browser by sending commands to a remote server. This server is expected to be running the WebDriver wire protocol as defined here: http://code.google.com/p/selenium/wiki/JsonWireProtocol Attributes: command_executor - The command.CommandExecutor object used to execute commands. error_handler - errorhandler.ErrorHandler object used to verify that the server did not return an error. session_id - The session ID to send with every command. capabilities - A dictionary of capabilities of the underlying browser for this instance's session. """ def __init__(self, command_executor, browser_name, platform, version="", javascript_enabled=True): """Create a new driver that will issue commands using the wire protocol. Args: command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. browser_name - A string indicating which browser to request a new session for from the remote server. Should be one of {mobile safari|firefox|internet explorer|htmlunit|chrome}. platform - A string indicating the desired platform to request from the remote server. Should be one of {WINDOWS|XP|VISTA|MAC|LINUX|UNIX|ANY}. version - A string indicating a specific browser version to request, or an empty string ot use any available browser. Defaults to the empty string. javascript_enabled - Whether the requested browser should support JavaScript. Defaults to True. """ self.command_executor = command_executor if type(self.command_executor) is str: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session( browser_name=browser_name, platform=platform, version=version, javascript_enabled=javascript_enabled ) @property def name(self): """Returns the name of the underlying browser for this instance.""" if "browserName" in self.capabilities: return self.capabilities["browserName"] else: raise KeyError("browserName not specified in session capabilities") def start_client(self): """Called before starting a new session. This method may be overridden to define custom startup behavior. """ pass def stop_client(self): """Called after executing a quit command. This method may be overridden to define custom shutdown behavior. """ pass def start_session(self, browser_name, platform=None, version=None, javascript_enabled=False): """Creates a new session with the desired capabilities. Args: browser_name: The name of the browser to request. version: Which browser version to request. platform: Which platform to request the browser on. javascript_enabled: Whether the new session should support JavaScript. """ response = self.execute( Command.NEW_SESSION, { "desiredCapabilities": { "browserName": browser_name, "platform": platform or "ANY", "version": version or "", "javascriptEnabled": javascript_enabled, } }, ) self.session_id = response["sessionId"] self.capabilities = response["value"] def _wrap_value(self, value): if isinstance(value, dict): converted = {} for key, val in value.items(): converted[key] = self._wrap_value(val) return converted elif isinstance(value, WebElement): return {"ELEMENT": value.id} elif isinstance(value, list): return list(self._wrap_value(item) for item in value) else: return value def create_web_element(self, element_id): return WebElement(self, element_id) def _unwrap_value(self, value): if isinstance(value, dict) and "ELEMENT" in value: return self.create_web_element(value["ELEMENT"]) elif isinstance(value, list): return list(self._unwrap_value(item) for item in value) else: return value def execute(self, driver_command, params=None): """Sends a command to be executed by a command.CommandExecutor. Args: driver_command: The name of the command to execute as a string. params: A dictionary of named parameters to send with the command. Returns: The command's JSON response loaded into a dictionary object. """ if not params: params = {"sessionId": self.session_id} elif "sessionId" not in params: params["sessionId"] = self.session_id params = self._wrap_value(params) response = self.command_executor.execute(driver_command, params) if response: self.error_handler.check_response(response) response["value"] = self._unwrap_value(response.get("value", None)) return response # If the server doesn't send a response, assume the command was # a success return {"success": 0, "value": None} def get(self, url): """Loads a web page in the current browser.""" self.execute(Command.GET, {"url": url}) @property def title(self): """Gets the title of the current page.""" resp = self.execute(Command.GET_TITLE) return resp["value"] if resp["value"] is not None else "" def find_element_by_id(self, id_): """Finds element by id.""" return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_): """Finds element by id.""" return self.find_elements(by=By.ID, value=id_) def find_elements_by_xpath(self, xpath): """Finds multiple elements by xpath.""" return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_xpath(self, xpath): """Finds an element by xpath.""" return self.find_element(by=By.XPATH, value=xpath) def find_element_by_link_text(self, link_text): """Finds an element by its link text.""" return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, link_text): """Finds elements by their link text.""" return self.find_elements(by=By.LINK_TEXT, value=link_text) def find_element_by_partial_link_text(self, link_text): """Finds an element by a partial match of its link text.""" return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text): """Finds elements by a partial match of their link text.""" return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_name(self, name): """Finds an element by its name.""" return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name): """Finds elements by their name.""" return self.find_elements(by=By.NAME, value=name) def find_element_by_tag_name(self, name): """Finds an element by its tag name.""" return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name): """Finds elements by their tag name.""" return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_class_name(self, name): """Finds an element by their class name.""" return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name): """Finds elements by their class name.""" return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector): """Find and return an element by CSS selector.""" return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector): """Find and return list of multiple elements by CSS selector.""" return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def execute_script(self, script, *args): if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute(Command.EXECUTE_SCRIPT, {"script": script, "args": converted_args})["value"] def execute_async_script(self, script, *args): if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute(Command.EXECUTE_ASYNC_SCRIPT, {"script": script, "args": converted_args})["value"] @property def current_url(self): """Gets the current url.""" return self.execute(Command.GET_CURRENT_URL)["value"] def get_page_source(self): """Gets the page source.""" return self.execute(Command.GET_PAGE_SOURCE)["value"] def close(self): """Closes the current window.""" self.execute(Command.CLOSE) def quit(self): """Quits the driver and close every associated window.""" try: self.execute(Command.QUIT) finally: self.stop_client() def get_current_window_handle(self): return self.execute(Command.GET_CURRENT_WINDOW_HANDLE)["value"] def get_window_handles(self): return self.execute(Command.GET_WINDOW_HANDLES)["value"] # Target Locators def switch_to_active_element(self): """Returns the element with focus, or BODY if nothing has focus.""" return self.execute(Command.GET_ACTIVE_ELEMENT)["value"] def switch_to_window(self, window_name): """Switches focus to a window.""" self.execute(Command.SWITCH_TO_WINDOW, {"name": window_name}) def switch_to_frame(self, index_or_name): """Switches focus to a frame by index or name.""" self.execute(Command.SWITCH_TO_FRAME, {"id": index_or_name}) def switch_to_default_content(self): """Switch to the default frame""" self.execute(Command.SWITCH_TO_FRAME, {"id": None}) def switch_to_alert(self): """ Switch to the alert on the page """ return Alert(self) # Navigation def back(self): """Goes back in browser history.""" self.execute(Command.GO_BACK) def forward(self): """Goes forward in browser history.""" self.execute(Command.GO_FORWARD) def refresh(self): """Refreshes the current page.""" self.execute(Command.REFRESH) # Options def get_cookies(self): """Gets all the cookies. Return a set of dicts.""" return self.execute(Command.GET_ALL_COOKIES)["value"] def get_cookie(self, name): """Get a single cookie. Returns the desired cookie dict or None.""" cookies = self.get_cookies() for cookie in cookies: if cookie["name"] == name: return cookie return None def delete_cookie(self, name): """Delete a cookie with the given name.""" self.execute(Command.DELETE_COOKIE, {"name": name}) def delete_all_cookies(self): """Delete all the cookies.""" self.execute(Command.DELETE_ALL_COOKIES) def add_cookie(self, cookie_dict): self.execute(Command.ADD_COOKIE, {"cookie": cookie_dict}) # Timeouts def implicitly_wait(self, time_to_wait): """Get the driver to poll for the element """ self.execute(Command.IMPLICIT_WAIT, {"ms": time_to_wait * 1000}) def set_script_timeout(self, time_to_wait): """Set the timeout that the script should wait before throwing an error""" self.execute(Command.SET_SCRIPT_TIMEOUT, {"ms": time_to_wait * 1000}) def find_element(self, by=By.ID, value=None): return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"] def find_elements(self, by=By.ID, value=None): return self.execute(Command.FIND_ELEMENTS, {"using": by, "value": value})["value"] def get_screenshot_as_file(self, filename): """Gets the screenshot of the current window. Returns False if there is any IOError, else returns True. Use full paths in your filename.""" png = self.execute(Command.SCREENSHOT)["value"] try: f = open(filename, "w") f.write(base64.decodestring(png)) f.close() except IOError: return False finally: del png return True def get_screenshot_as_base64(self): """Gets the screenshot of the current window as a base64 encoded string which is useful in embedded images in HTML.""" return self.execute(Command.SCREENSHOT)["value"]
def __init__(self, level=logging.ERROR, message='No output as errors have occurred.'): from errorhandler import ErrorHandler self.handler = ErrorHandler(level) self.message = message
class Controller(object): """ Parent class to all Controller classes. """ def __init__(self): self.error_handle = ErrorHandler() self.cache_handle = Cache def get_db_handler(self): """ Returns the DB handler """ mc = MongoClient() return mc[current_app.config["DB"]["name"]] def add_db_item(self, collection=None, content=None, _id=None, upsert=False): """ Save an item to the DB """ try: if collection and content: db = self.get_db_handler() _id = db[collection].save(content) return { "status": "success", "message": "Successfully added item to the DB", "_id": _id } return None except Exception as e: return self.error_handle.get_error( error=str(e), occurred_at="mad.lib.controller.add_db_item()") def update_db_item(self, collection=None, conditions=None, content=None, upsert=False, overwrite=False, noobjectify=False, multi=False): """ Update/upsert a DB item """ try: if collection and conditions and content: db = self.get_db_handler() if noobjectify == False and "_id" in conditions: conditions["_id"] = ObjectId(conditions["_id"]) if overwrite: db[collection].update(conditions, {"$set": content}, upsert=upsert, multi=multi) else: db[collection].update(conditions, content, upsert=upsert, multi=multi) return { "status": "success", "message": "DB item updated successfully." } except Exception as e: return self.error_handle.get_error( error=str(e), occurred_at="mad.lib.controller.update_db_item()") def get_db_items(self, collection=None, conditions=None, sort_by=[("_id", 1)]): """ Get items from a collection in the DB and return results """ try: if collection: if conditions and "_id" in conditions: # By default, if an _id is provided, it'll be converted into an ObjectId instance. # "noobjectify" would prevent it from making use of the _id directly instead of # converting it into an ObjectId instance. if not "noobjectify" in conditions or conditions[ "noobjectify"] == False: conditions.update({"_id": ObjectId(conditions["_id"])}) items = self.get_db_handler()[collection].find( conditions).sort(sort_by) if items: return items return None except Exception as e: return self.error_handle.get_error( error=str(e), occurred_at="mad.lib.controller.get_db_items()") def get_db_distinct_items(self, collection=None, fieldname=None, conditions=None, sort_by=[("_id", 1)]): """ Get unique/distinct values from all records of the given field """ try: if collection and fieldname: return self.get_db_handler()[collection].find(conditions).sort( sort_by).distinct(fieldname) return None except Exception as e: return self.error_handle.get_error( error=str(e), occurred_at="mad.lib.controller.get_db_distinct_items()") def remove_db_item(self, collection=None, conditions=None, remove_all=False): """ Remove an or all items from the collection, based on given conditions """ try: if remove_all: conditions = {} if collection and conditions: self.get_db_handler()[collection].remove(conditions) return { "status": "success", "message": "Successfully removed item(s) from the DB" } except Exception as e: return self.error_handle.get_error( error=str(e), occurred_at="mad.lib.controller.remove_db_item()")
class WebDriver(object): """Controls a browser by sending commands to a remote server. This server is expected to be running the WebDriver wire protocol as defined here: http://code.google.com/p/selenium/wiki/JsonWireProtocol Attributes: command_executor - The command.CommandExecutor object used to execute commands. error_handler - errorhandler.ErrorHandler object used to verify that the server did not return an error. session_id - The session ID to send with every command. capabilities - A dictionary of capabilities of the underlying browser for this instance's session. """ def __init__(self, command_executor, browser_name, platform, version='', javascript_enabled=True): """Create a new driver that will issue commands using the wire protocol. Args: command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. browser_name - A string indicating which browser to request a new session for from the remote server. Should be one of {mobile safari|firefox|internet explorer|htmlunit|chrome}. platform - A string indicating the desired platform to request from the remote server. Should be one of {WINDOWS|XP|VISTA|MAC|LINUX|UNIX|ANY}. version - A string indicating a specific browser version to request, or an empty string ot use any available browser. Defaults to the empty string. javascript_enabled - Whether the requested browser should support JavaScript. Defaults to True. """ self.command_executor = command_executor if type(self.command_executor) is str: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(browser_name=browser_name, platform=platform, version=version, javascript_enabled=javascript_enabled) @property def name(self): """Returns the name of the underlying browser for this instance.""" if 'browserName' in self.capabilities: return self.capabilities['browserName'] else: raise KeyError('browserName not specified in session capabilities') def start_client(self): """Called before starting a new session. This method may be overridden to define custom startup behavior. """ pass def stop_client(self): """Called after executing a quit command. This method may be overridden to define custom shutdown behavior. """ pass def start_session(self, browser_name, platform=None, version=None, javascript_enabled=False): """Creates a new session with the desired capabilities. Args: browser_name: The name of the browser to request. version: Which browser version to request. platform: Which platform to request the browser on. javascript_enabled: Whether the new session should support JavaScript. """ response = self._execute(Command.NEW_SESSION, { 'desiredCapabilities': { 'browserName': browser_name, 'platform': platform or 'ANY', 'version': version or '', 'javascriptEnabled': javascript_enabled } }) self.session_id = response['sessionId'] self.capabilities = response['value'] def _wrap_value(self, value): if isinstance(value, dict): converted = {} for key, val in value.items(): converted[key] = self._wrap_value(val) return converted elif isinstance(value, WebElement): return {'ELEMENT': value.id} elif isinstance(value, list): return list(self._wrap_value(item) for item in value) else: return value def create_web_element(self, element_id): return WebElement(self, element_id) def _unwrap_value(self, value): if isinstance(value, dict) and 'ELEMENT' in value: return self.create_web_element(value['ELEMENT']) elif isinstance(value, list): return list(self._unwrap_value(item) for item in value) else: return value def _execute(self, driver_command, params=None): """Sends a command to be executed by a command.CommandExecutor. Args: driver_command: The name of the command to execute as a string. params: A dictionary of named parameters to send with the command. Returns: The command's JSON response loaded into a dictionary object. """ if not params: params = {'sessionId': self.session_id} elif 'sessionId' not in params: params['sessionId'] = self.session_id params = self._wrap_value(params) response = self.command_executor.execute(driver_command, params) if response: self.error_handler.check_response(response) response['value'] = self._unwrap_value( response.get('value', None)) return response # If the server doesn't send a response, assume the command was # a success return {'success': 0, 'value': None} def get(self, url): """Loads a web page in the current browser.""" self._execute(Command.GET, {'url': url}) def get_title(self): """Gets the title of the current page.""" resp = self._execute(Command.GET_TITLE) return resp['value'] def find_element_by_id(self, id_): """Finds element by id.""" return self._find_element_by("id", id_) def find_elements_by_xpath(self, xpath): """Finds multiple elements by xpath.""" return self._find_elements_by("xpath", xpath) def find_element_by_xpath(self, xpath): """Finds an element by xpath.""" return self._find_element_by("xpath", xpath) def find_element_by_link_text(self, link_text): """Finds an element by its link text.""" return self._find_element_by("link text", link_text) def find_element_by_partial_link_text(self, link_text): """Finds an element by a partial match of its link text.""" return self._find_element_by("partial link text", link_text) def find_elements_by_partial_link_text(self, link_text): """Finds elements by a partial match of their link text.""" return self._find_elements_by("partial link text", link_text) def find_element_by_name(self, name): """Finds an element by its name.""" return self._find_element_by("name", name) def find_elements_by_name(self, name): """Finds elements by their name.""" return self._find_elements_by("name", name) def find_element_by_tag_name(self, name): """Finds an element by its tag name.""" return self._find_element_by("tag name", name) def find_elements_by_tag_name(self, name): """Finds elements by their tag name.""" return self._find_elements_by("tag name", name) def execute_script(self, script, *args): if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self._execute( Command.EXECUTE_SCRIPT, {'script': script, 'args':converted_args})['value'] def get_current_url(self): """Gets the current url.""" return self._execute(Command.GET_CURRENT_URL)['value'] def get_page_source(self): """Gets the page source.""" return self._execute(Command.GET_PAGE_SOURCE)['value'] def close(self): """Closes the current window.""" self._execute(Command.CLOSE) def quit(self): """Quits the driver and close every associated window.""" try: self._execute(Command.QUIT) finally: self.stop_client() def get_current_window_handle(self): return self._execute(Command.GET_CURRENT_WINDOW_HANDLE)['value'] def get_window_handles(self): return self._execute(Command.GET_WINDOW_HANDLES)['value'] def switch_to_active_element(self): """Returns the element with focus, or BODY if nothing has focus.""" return self._execute(Command.GET_ACTIVE_ELEMENT)['value'] def switch_to_window(self, window_name): """Switches focus to a window.""" self._execute(Command.SWITCH_TO_WINDOW, {'name': window_name}) def switch_to_frame(self, index_or_name): """Switches focus to a frame by index or name.""" self._execute(Command.SWITCH_TO_FRAME, {'id': index_or_name}) def back(self): """Goes back in browser history.""" self._execute(Command.GO_BACK) def forward(self): """Goes forward in browser history.""" self._execute(Command.GO_FORWARD) # Options def get_cookies(self): """Gets all the cookies. Return a set of dicts.""" return self._execute(Command.GET_ALL_COOKIES)['value'] def get_cookie(self, name): """Get a single cookie. Returns the desired cookie dict or None.""" cookies = self.get_cookies() for cookie in cookies: if cookie['name'] == name: return cookie return None def delete_cookie(self, name): """Delete a cookie with the given name.""" self._execute(Command.DELETE_COOKIE, {'name': name}) def delete_all_cookies(self): """Delete all the cookies.""" self._execute(Command.DELETE_ALL_COOKIES) def add_cookie(self, cookie_dict): self._execute(Command.ADD_COOKIE, {'cookie': cookie_dict}) def _find_element_by(self, by, value): return self._execute(Command.FIND_ELEMENT, {'using': by, 'value': value})['value'] def _find_elements_by(self, by, value): return self._execute(Command.FIND_ELEMENTS, {'using': by, 'value': value})['value']
class WebDriver(object): """Controls a browser by sending commands to a remote server. This server is expected to be running the WebDriver wire protocol as defined here: http://code.google.com/p/selenium/wiki/JsonWireProtocol Attributes: command_executor - The command.CommandExecutor object used to execute commands. error_handler - errorhandler.ErrorHandler object used to verify that the server did not return an error. session_id - The session ID to send with every command. capabilities - A dictionary of capabilities of the underlying browser for this instance's session.""" def __init__( self, command_executor="http://127.0.0.1:4444/wd/hub", desired_capabilities=None, browser_profile=None ): """Create a new driver that will issue commands using the wire protocol. Args: command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. desired_capabilities - Dictionary holding predefined values for starting a browser browser_profile: A browser profile directory as a Base64-encoded zip file. Only used if Firefox is requested. """ if desired_capabilities is None: raise WebDriverException("Desired Capabilities can't be None") self.command_executor = command_executor if type(self.command_executor) is str: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(desired_capabilities, browser_profile) @property def name(self): """Returns the name of the underlying browser for this instance. Usage: driver.name """ if "browserName" in self.capabilities: return self.capabilities["browserName"] else: raise KeyError("browserName not specified in session capabilities") def start_client(self): """Called before starting a new session. This method may be overridden to define custom startup behavior.""" pass def stop_client(self): """Called after executing a quit command. This method may be overridden to define custom shutdown behavior.""" pass def start_session(self, desired_capabilities, browser_profile=None): """Creates a new session with the desired capabilities. Args: browser_name: The name of the browser to request. version: Which browser version to request. platform: Which platform to request the browser on. javascript_enabled: Whether the new session should support JavaScript. browser_profile: A browser profile directory as a Base64-encoded zip file. Only used if Firefox is requested. """ if browser_profile: desired_capabilities["firefox_profile"] = browser_profile.encoded response = self.execute(Command.NEW_SESSION, {"desiredCapabilities": desired_capabilities}) self.session_id = response["sessionId"] self.capabilities = response["value"] def _wrap_value(self, value): if isinstance(value, dict): converted = {} for key, val in value.items(): converted[key] = self._wrap_value(val) return converted elif isinstance(value, WebElement): return {"ELEMENT": value.id} elif isinstance(value, list): return list(self._wrap_value(item) for item in value) else: return value def create_web_element(self, element_id): """Creates a web element with the specified element_id.""" return WebElement(self, element_id) def _unwrap_value(self, value): if isinstance(value, dict) and "ELEMENT" in value: return self.create_web_element(value["ELEMENT"]) elif isinstance(value, list): return list(self._unwrap_value(item) for item in value) else: return value def execute(self, driver_command, params=None): """Sends a command to be executed by a command.CommandExecutor. Args: driver_command: The name of the command to execute as a string. params: A dictionary of named parameters to send with the command. Returns: The command's JSON response loaded into a dictionary object. """ if not params: params = {"sessionId": self.session_id} elif "sessionId" not in params: params["sessionId"] = self.session_id params = self._wrap_value(params) response = self.command_executor.execute(driver_command, params) if response: self.error_handler.check_response(response) response["value"] = self._unwrap_value(response.get("value", None)) return response # If the server doesn't send a response, assume the command was # a success return {"success": 0, "value": None} def get(self, url): """Loads a web page in the current browser session.""" self.execute(Command.GET, {"url": url}) @property def title(self): """Returns the title of the current page. Usage: driver.title """ resp = self.execute(Command.GET_TITLE) return resp["value"] if resp["value"] is not None else "" def find_element_by_id(self, id_): """Finds an element by id. Args: id_: The id of the element to be found. Usage: driver.find_element_by_id('foo') """ return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_): """Finds multiple elements by id. Args: id_: The id of the elements to be found. Usage: driver.find_element_by_id('foo') """ return self.find_elements(by=By.ID, value=id_) def find_element_by_xpath(self, xpath): """Finds an element by xpath. Args: xpath: The xpath locator of the element to find. Usage: driver.find_element_by_xpath('//div/td[1]') """ return self.find_element(by=By.XPATH, value=xpath) def find_elements_by_xpath(self, xpath): """Finds multiple elements by xpath. Args: xpath: The xpath locator of the elements to be found. Usage: driver.find_elements_by_xpath("//div[contains(@class, 'foo')]") """ return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_link_text(self, link_text): """Finds an element by link text. Args: link_text: The text of the element to be found. Usage: driver.find_element_by_link_text('Sign In') """ return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, text): """Finds elements by link text. Args: link_text: The text of the elements to be found. Usage: driver.find_elements_by_link_text('Sign In') """ return self.find_elements(by=By.LINK_TEXT, value=text) def find_element_by_partial_link_text(self, link_text): """Finds an element by a partial match of its link text. Args: link_text: The text of the element to partially match on. Usage: driver.find_element_by_partial_link_text('Sign') """ return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text): """Finds elements by a partial match of their link text. Args: link_text: The text of the element to partial match on. Usage: driver.find_element_by_partial_link_text('Sign') """ return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_name(self, name): """Finds an element by name. Args: name: The name of the element to find. Usage: driver.find_element_by_name('foo') """ return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name): """Finds elements by name. Args: name: The name of the elements to find. Usage: driver.find_elements_by_name('foo') """ return self.find_elements(by=By.NAME, value=name) def find_element_by_tag_name(self, name): """Finds an element by tag name. Args: name: The tag name of the element to find. Usage: driver.find_element_by_tag_name('foo') """ return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name): """Finds elements by tag name. Args: name: The tag name the use when finding elements. Usage: driver.find_elements_by_tag_name('foo') """ return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_class_name(self, name): """Finds an element by class name. Args: name: The class name of the element to find. Usage: driver.find_element_by_class_name('foo') """ return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name): """Finds elements by class name. Args: name: The class name of the elements to find. Usage: driver.find_elements_by_class_name('foo') """ return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector): """Finds an element by css selector. Args: css_selector: The css selector to use when finding elements. Usage: driver.find_element_by_css_selector('#foo') """ return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector): """Finds elements by css selector. Args: css_selector: The css selector to use when finding elements. Usage: driver.find_element_by_css_selector('#foo') """ return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def execute_script(self, script, *args): """Synchronously Executes JavaScript in the current window/frame. Args: script: The JavaScript to execute. *args: Any applicable arguments for your JavaScript. Usage: driver.execute_script('document.title') """ if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute(Command.EXECUTE_SCRIPT, {"script": script, "args": converted_args})["value"] def execute_async_script(self, script, *args): """Asynchronously Executes JavaScript in the current window/frame. Args: script: The JavaScript to execute. args: Any applicable arguments for your JavaScript. Usage: driver.execute_async_script('document.title') """ if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute(Command.EXECUTE_ASYNC_SCRIPT, {"script": script, "args": converted_args})["value"] @property def current_url(self): """Gets the URL of the current page. Usage: driver.current_url """ return self.execute(Command.GET_CURRENT_URL)["value"] def get_page_source(self): """Gets the source of the current page. Usage: driver.get_page_source() """ return self.execute(Command.GET_PAGE_SOURCE)["value"] def close(self): """Closes the current window. Usage: driver.close() """ self.execute(Command.CLOSE) def quit(self): """Quits the driver and closes every associated window. Usage: driver.quit() """ try: self.execute(Command.QUIT) finally: self.stop_client() def get_current_window_handle(self): """Returns the handle of the current window. Usage: driver.get_current_window_handle() """ return self.execute(Command.GET_CURRENT_WINDOW_HANDLE)["value"] def get_window_handles(self): """Returns the handles of all windows within the current session. Usage: driver.get_window_handles() """ return self.execute(Command.GET_WINDOW_HANDLES)["value"] # Target Locators def switch_to_active_element(self): """Returns the element with focus, or BODY if nothing has focus. Usage: driver.switch_to_active_element() """ return self.execute(Command.GET_ACTIVE_ELEMENT)["value"] def switch_to_window(self, window_name): """Switches focus to the specified window. Args: window_name: The name of the window to switch to. Usage: driver.switch_to_window('main') """ self.execute(Command.SWITCH_TO_WINDOW, {"name": window_name}) def switch_to_frame(self, index_or_name): """Switches focus to the specified frame, by index or name. Args: index_or_name: The name of the window to switch to, or an integer representing the index to switch to. Usage: driver.switch_to_frame('frame_name') driver.switch_to_frame(1) """ self.execute(Command.SWITCH_TO_FRAME, {"id": index_or_name}) def switch_to_default_content(self): """Switch focus to the default frame. Usage: driver.switch_to_default_content() """ self.execute(Command.SWITCH_TO_FRAME, {"id": None}) def switch_to_alert(self): """Switches focus to an alert on the page. Usage: driver.switch_to_alert() """ return Alert(self) # Navigation def back(self): """Goes one step backward in the browser history. Usage: driver.back() """ self.execute(Command.GO_BACK) def forward(self): """Goes one step forward in the browser history. Usage: driver.forward() """ self.execute(Command.GO_FORWARD) def refresh(self): """Refreshes the current page. Usage: driver.refresh() """ self.execute(Command.REFRESH) # Options def get_cookies(self): """Returns a set of dictionaries, corresponding to cookies visible in the current session. Usage: driver.get_cookies() """ return self.execute(Command.GET_ALL_COOKIES)["value"] def get_cookie(self, name): """Get a single cookie by name. Returns the cookie if found, None if not. Usage: driver.get_cookie('my_cookie') """ cookies = self.get_cookies() for cookie in cookies: if cookie["name"] == name: return cookie return None def delete_cookie(self, name): """Deletes a single cookie with the given name. Usage: driver.delete_cookie('my_cookie') """ self.execute(Command.DELETE_COOKIE, {"name": name}) def delete_all_cookies(self): """Delete all cookies in the scope of the session. Usage: driver.delete_all_cookies() """ self.execute(Command.DELETE_ALL_COOKIES) def add_cookie(self, cookie_dict): """Adds a cookie to your current session. Args: cookie_dict: A dictionary object, with the desired cookie name as the key, and the value being the desired contents. Usage: driver.add_cookie({'foo': 'bar',}) """ self.execute(Command.ADD_COOKIE, {"cookie": cookie_dict}) # Timeouts def implicitly_wait(self, time_to_wait): """Sets a sticky timeout to implicitly wait for an element to be found, or a command to complete. This method only needs to be called one time per session. Args: time_to_wait: Amount of time to wait Usage: driver.implicitly_wait(30) """ self.execute(Command.IMPLICIT_WAIT, {"ms": int(time_to_wait) * 1000}) def set_script_timeout(self, time_to_wait): """Set the amount of time that the script should wait before throwing an error. Args: time_to_wait: The amount of time to wait Usage: driver.set_script_timeout(30) """ self.execute(Command.SET_SCRIPT_TIMEOUT, {"ms": int(time_to_wait) * 1000}) def find_element(self, by=By.ID, value=None): """'Private' method used by the find_element_by_* methods. Usage: Use the corresponding find_element_by_* instead of this. """ return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"] def find_elements(self, by=By.ID, value=None): """'Private' method used by the find_elements_by_* methods. Usage: Use the corresponding find_elements_by_* instead of this. """ return self.execute(Command.FIND_ELEMENTS, {"using": by, "value": value})["value"] def get_screenshot_as_file(self, filename): """Gets the screenshot of the current window. Returns False if there is any IOError, else returns True. Use full paths in your filename. Args: filename: The full path you wish to save your screenshot to. Usage: driver.get_screenshot_as_file('/Screenshots/foo.png') """ png = self.execute(Command.SCREENSHOT)["value"] try: with open(filename, "wb") as f: f.write(base64.decodestring(png)) except IOError: return False del png return True def get_screenshot_as_base64(self): """Gets the screenshot of the current window as a base64 encoded string which is useful in embedded images in HTML. Usage: driver.get_screenshot_as_base64() """ return self.execute(Command.SCREENSHOT)["value"]
class WebDriver(object): """ Controls a browser by sending commands to a remote server. This server is expected to be running the WebDriver wire protocol as defined here: http://code.google.com/p/selenium/wiki/JsonWireProtocol :Attributes: - command_executor - The command.CommandExecutor object used to execute commands. - error_handler - errorhandler.ErrorHandler object used to verify that the server did not return an error. - session_id - The session ID to send with every command. - capabilities - A dictionary of capabilities of the underlying browser for this instance's session. """ def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities=None, browser_profile=None): """ Create a new driver that will issue commands using the wire protocol. :Args: - command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. - desired_capabilities - Dictionary holding predefined values for starting a browser - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. """ if desired_capabilities is None: raise WebDriverException("Desired Capabilities can't be None") self.command_executor = command_executor if type(self.command_executor) is str: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(desired_capabilities, browser_profile) @property def name(self): """Returns the name of the underlying browser for this instance. :Usage: - driver.name """ if 'browserName' in self.capabilities: return self.capabilities['browserName'] else: raise KeyError('browserName not specified in session capabilities') def start_client(self): """ Called before starting a new session. This method may be overridden to define custom startup behavior. """ pass def stop_client(self): """ Called after executing a quit command. This method may be overridden to define custom shutdown behavior. """ pass def start_session(self, desired_capabilities, browser_profile=None): """ Creates a new session with the desired capabilities. :Args: - browser_name - The name of the browser to request. - version - Which browser version to request. - platform - Which platform to request the browser on. - javascript_enabled - Whether the new session should support JavaScript. - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. """ if browser_profile: desired_capabilities['firefox_profile'] = browser_profile.encoded response = self.execute(Command.NEW_SESSION, { 'desiredCapabilities': desired_capabilities, }) self.session_id = response['sessionId'] self.capabilities = response['value'] def _wrap_value(self, value): if isinstance(value, dict): converted = {} for key, val in value.items(): converted[key] = self._wrap_value(val) return converted elif isinstance(value, WebElement): return {'ELEMENT': value.id} elif isinstance(value, list): return list(self._wrap_value(item) for item in value) else: return value def create_web_element(self, element_id): """ Creates a web element with the specified element_id. """ return WebElement(self, element_id) def _unwrap_value(self, value): if isinstance(value, dict) and 'ELEMENT' in value: return self.create_web_element(value['ELEMENT']) elif isinstance(value, list): return list(self._unwrap_value(item) for item in value) else: return value def execute(self, driver_command, params=None): """ Sends a command to be executed by a command.CommandExecutor. :Args: - driver_command: The name of the command to execute as a string. - params: A dictionary of named parameters to send with the command. :Returns: The command's JSON response loaded into a dictionary object. """ if not params: params = {'sessionId': self.session_id} elif 'sessionId' not in params: params['sessionId'] = self.session_id params = self._wrap_value(params) response = self.command_executor.execute(driver_command, params) if response: self.error_handler.check_response(response) response['value'] = self._unwrap_value( response.get('value', None)) return response # If the server doesn't send a response, assume the command was # a success return {'success': 0, 'value': None, 'sessionId': self.session_id} def get(self, url): """ Loads a web page in the current browser session. """ self.execute(Command.GET, {'url': url}) @property def title(self): """Returns the title of the current page. :Usage: driver.title """ resp = self.execute(Command.GET_TITLE) return resp['value'] if resp['value'] is not None else "" def find_element_by_id(self, id_): """Finds an element by id. :Args: - id\_ - The id of the element to be found. :Usage: driver.find_element_by_id('foo') """ return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_): """ Finds multiple elements by id. :Args: - id\_ - The id of the elements to be found. :Usage: driver.find_element_by_id('foo') """ return self.find_elements(by=By.ID, value=id_) def find_element_by_xpath(self, xpath): """ Finds an element by xpath. :Args: - xpath - The xpath locator of the element to find. :Usage: driver.find_element_by_xpath('//div/td[1]') """ return self.find_element(by=By.XPATH, value=xpath) def find_elements_by_xpath(self, xpath): """ Finds multiple elements by xpath. :Args: - xpath - The xpath locator of the elements to be found. :Usage: driver.find_elements_by_xpath("//div[contains(@class, 'foo')]") """ return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_link_text(self, link_text): """ Finds an element by link text. :Args: - link_text: The text of the element to be found. :Usage: driver.find_element_by_link_text('Sign In') """ return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, text): """ Finds elements by link text. :Args: - link_text: The text of the elements to be found. :Usage: driver.find_elements_by_link_text('Sign In') """ return self.find_elements(by=By.LINK_TEXT, value=text) def find_element_by_partial_link_text(self, link_text): """ Finds an element by a partial match of its link text. :Args: - link_text: The text of the element to partially match on. :Usage: driver.find_element_by_partial_link_text('Sign') """ return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text): """ Finds elements by a partial match of their link text. :Args: - link_text: The text of the element to partial match on. :Usage: driver.find_element_by_partial_link_text('Sign') """ return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_name(self, name): """ Finds an element by name. :Args: - name: The name of the element to find. :Usage: driver.find_element_by_name('foo') """ return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name): """ Finds elements by name. :Args: - name: The name of the elements to find. :Usage: driver.find_elements_by_name('foo') """ return self.find_elements(by=By.NAME, value=name) def find_element_by_tag_name(self, name): """ Finds an element by tag name. :Args: - name: The tag name of the element to find. :Usage: driver.find_element_by_tag_name('foo') """ return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name): """ Finds elements by tag name. :Args: - name: The tag name the use when finding elements. :Usage: driver.find_elements_by_tag_name('foo') """ return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_class_name(self, name): """ Finds an element by class name. :Args: - name: The class name of the element to find. :Usage: driver.find_element_by_class_name('foo') """ return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name): """ Finds elements by class name. :Args: - name: The class name of the elements to find. :Usage: driver.find_elements_by_class_name('foo') """ return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector): """ Finds an element by css selector. :Args: - css_selector: The css selector to use when finding elements. :Usage: driver.find_element_by_css_selector('#foo') """ return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector): """ Finds elements by css selector. :Args: - css_selector: The css selector to use when finding elements. :Usage: driver.find_element_by_css_selector('#foo') """ return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def execute_script(self, script, *args): """ Synchronously Executes JavaScript in the current window/frame. :Args: - script: The JavaScript to execute. - \*args: Any applicable arguments for your JavaScript. :Usage: driver.execute_script('document.title') """ if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute(Command.EXECUTE_SCRIPT, {'script': script, 'args':converted_args})['value'] def execute_async_script(self, script, *args): """ Asynchronously Executes JavaScript in the current window/frame. :Args: - script: The JavaScript to execute. - \*args: Any applicable arguments for your JavaScript. :Usage: driver.execute_async_script('document.title') """ if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute(Command.EXECUTE_ASYNC_SCRIPT, {'script': script, 'args':converted_args})['value'] @property def current_url(self): """ Gets the URL of the current page. :Usage: driver.current_url """ return self.execute(Command.GET_CURRENT_URL)['value'] @property def page_source(self): """ Gets the source of the current page. :Usage: driver.page_source """ return self.execute(Command.GET_PAGE_SOURCE)['value'] def close(self): """ Closes the current window. :Usage: driver.close() """ self.execute(Command.CLOSE) def quit(self): """ Quits the driver and closes every associated window. :Usage: driver.quit() """ try: self.execute(Command.QUIT) finally: self.stop_client() @property def current_window_handle(self): """ Returns the handle of the current window. :Usage: driver.current_window_handle """ return self.execute(Command.GET_CURRENT_WINDOW_HANDLE)['value'] @property def window_handles(self): """ Returns the handles of all windows within the current session. :Usage: driver.window_handles """ return self.execute(Command.GET_WINDOW_HANDLES)['value'] def maximize_window(self): """ Maximizes the current window that webdriver is using """ self.execute(Command.MAXIMIZE_WINDOW, {"windowHandle": "current"}) #Target Locators def switch_to_active_element(self): """ Returns the element with focus, or BODY if nothing has focus. :Usage: driver.switch_to_active_element() """ return self.execute(Command.GET_ACTIVE_ELEMENT)['value'] def switch_to_window(self, window_name): """ Switches focus to the specified window. :Args: - window_name: The name or window handle of the window to switch to. :Usage: driver.switch_to_window('main') """ self.execute(Command.SWITCH_TO_WINDOW, {'name': window_name}) def switch_to_frame(self, frame_reference): """ Switches focus to the specified frame, by index, name, or webelement. :Args: - frame_reference: The name of the window to switch to, an integer representing the index, or a webelement that is an (i)frame to switch to. :Usage: driver.switch_to_frame('frame_name') driver.switch_to_frame(1) driver.switch_to_frame(driver.find_elements_by_tag_name("iframe")[0]) """ self.execute(Command.SWITCH_TO_FRAME, {'id': frame_reference}) def switch_to_default_content(self): """ Switch focus to the default frame. :Usage: driver.switch_to_default_content() """ self.execute(Command.SWITCH_TO_FRAME, {'id': None}) def switch_to_alert(self): """ Switches focus to an alert on the page. :Usage: driver.switch_to_alert() """ return Alert(self) #Navigation def back(self): """ Goes one step backward in the browser history. :Usage: driver.back() """ self.execute(Command.GO_BACK) def forward(self): """ Goes one step forward in the browser history. :Usage: driver.forward() """ self.execute(Command.GO_FORWARD) def refresh(self): """ Refreshes the current page. :Usage: driver.refresh() """ self.execute(Command.REFRESH) # Options def get_cookies(self): """ Returns a set of dictionaries, corresponding to cookies visible in the current session. :Usage: driver.get_cookies() """ return self.execute(Command.GET_ALL_COOKIES)['value'] def get_cookie(self, name): """ Get a single cookie by name. Returns the cookie if found, None if not. :Usage: driver.get_cookie('my_cookie') """ cookies = self.get_cookies() for cookie in cookies: if cookie['name'] == name: return cookie return None def delete_cookie(self, name): """ Deletes a single cookie with the given name. :Usage: driver.delete_cookie('my_cookie') """ self.execute(Command.DELETE_COOKIE, {'name': name}) def delete_all_cookies(self): """ Delete all cookies in the scope of the session. :Usage: driver.delete_all_cookies() """ self.execute(Command.DELETE_ALL_COOKIES) def add_cookie(self, cookie_dict): """ Adds a cookie to your current session. :Args: - cookie_dict: A dictionary object, with required keys - "name" and "value"; optional keys - "path", "domain", "secure", "expiry" Usage: driver.add_cookie({'name' : 'foo', 'value' : 'bar'}) driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/'}) driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/', 'secure':True}) """ self.execute(Command.ADD_COOKIE, {'cookie': cookie_dict}) # Timeouts def implicitly_wait(self, time_to_wait): """ Sets a sticky timeout to implicitly wait for an element to be found, or a command to complete. This method only needs to be called one time per session. To set the timeout for calls to execute_async_script, see set_script_timeout. :Args: - time_to_wait: Amount of time to wait (in seconds) :Usage: driver.implicitly_wait(30) """ self.execute(Command.IMPLICIT_WAIT, {'ms': float(time_to_wait) * 1000}) def set_script_timeout(self, time_to_wait): """ Set the amount of time that the script should wait during an execute_async_script call before throwing an error. :Args: - time_to_wait: The amount of time to wait :Usage: driver.set_script_timeout(30) """ self.execute(Command.SET_SCRIPT_TIMEOUT, {'ms': float(time_to_wait) * 1000}) def find_element(self, by=By.ID, value=None): """ 'Private' method used by the find_element_by_* methods. :Usage: Use the corresponding find_element_by_* instead of this. """ return self.execute(Command.FIND_ELEMENT, {'using': by, 'value': value})['value'] def find_elements(self, by=By.ID, value=None): """ 'Private' method used by the find_elements_by_* methods. :Usage: Use the corresponding find_elements_by_* instead of this. """ return self.execute(Command.FIND_ELEMENTS, {'using': by, 'value': value})['value'] @property def desired_capabilities(self): """ returns the drivers current desired capabilities being used """ return self.capabilities def get_screenshot_as_file(self, filename): """ Gets the screenshot of the current window. Returns False if there is any IOError, else returns True. Use full paths in your filename. :Args: - filename: The full path you wish to save your screenshot to. :Usage: driver.get_screenshot_as_file('/Screenshots/foo.png') """ png = self.execute(Command.SCREENSHOT)['value'] try: with open(filename, 'wb') as f: f.write(base64.decodestring(png)) except IOError: return False del png return True def get_screenshot_as_base64(self): """ Gets the screenshot of the current window as a base64 encoded string which is useful in embedded images in HTML. :Usage: driver.get_screenshot_as_base64() """ return self.execute(Command.SCREENSHOT)['value'] def set_window_size(self, width, height, windowHandle='current'): """ Sets the width and height of the current window. (window.resizeTo) :Args: - width: the width in pixels to set the window to - height: the height in pixels to set the window to :Usage: driver.set_window_size(800,600) """ self.execute(Command.SET_WINDOW_SIZE, {'width': width, 'height': height, 'windowHandle': windowHandle}) def get_window_size(self, windowHandle='current'): """ Gets the width and height of the current window. :Usage: driver.get_window_size() """ return self.execute(Command.GET_WINDOW_SIZE, {'windowHandle': windowHandle})['value'] def set_window_position(self, x, y, windowHandle='current'): """ Sets the x,y position of the current window. (window.moveTo) :Args: - x: the x-coordinate in pixels to set the window position - y: the y-coordinate in pixels to set the window position :Usage: driver.set_window_position(0,0) """ self.execute(Command.SET_WINDOW_POSITION, {'x': x, 'y': y, 'windowHandle': windowHandle}) def get_window_position(self, windowHandle='current'): """ Gets the x,y position of the current window. :Usage: driver.get_window_position() """ return self.execute(Command.GET_WINDOW_POSITION, {'windowHandle': windowHandle})['value'] @property def orientation(self): """ Gets the current orientation of the device :Usage: orientation = driver.orientation """ return self.execute(Command.GET_SCREEN_ORIENTATION)['value'] @orientation.setter def orientation(self, value): """ Sets the current orientation of the device :Args: - value: orientation to set it to. :Usage: driver.orientation = 'landscape' """ allowed_values = ['LANDSCAPE', 'PORTRAIT'] if value.upper() in allowed_values: self.execute(Command.SET_SCREEN_ORIENTATION, {'orientation': value})['value'] else: raise WebDriverException("You can only set the orientation to 'LANDSCAPE' and 'PORTRAIT'")
class RemoteConnection(object): """A connection with the Remote WebDriver server. Communicates with the server using the WebDriver wire protocol: https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol""" _timeout = socket._GLOBAL_DEFAULT_TIMEOUT @classmethod def get_timeout(cls): """ :Returns: Timeout value in seconds for all http requests made to the Remote Connection """ return None if cls._timeout == socket._GLOBAL_DEFAULT_TIMEOUT else cls._timeout @classmethod def set_timeout(cls, timeout): """ Override the default timeout :Args: - timeout - timeout value for http requests in seconds """ cls._timeout = timeout @classmethod def reset_timeout(cls): """ Reset the http request timeout to socket._GLOBAL_DEFAULT_TIMEOUT """ cls._timeout = socket._GLOBAL_DEFAULT_TIMEOUT def __init__(self, remote_server_addr, keep_alive=False): # Attempt to resolve the hostname and get an IP address. self.keep_alive = keep_alive self.error_handler = ErrorHandler() parsed_url = parse.urlparse(remote_server_addr) addr = "" if parsed_url.hostname: try: netloc = socket.gethostbyname(parsed_url.hostname) addr = netloc if parsed_url.port: netloc += ':%d' % parsed_url.port if parsed_url.username: auth = parsed_url.username if parsed_url.password: auth += ':%s' % parsed_url.password netloc = '%s@%s' % (auth, netloc) remote_server_addr = parse.urlunparse( (parsed_url.scheme, netloc, parsed_url.path, parsed_url.params, parsed_url.query, parsed_url.fragment)) except socket.gaierror: LOGGER.info('Could not get IP address for host: %s' % parsed_url.hostname) self._url = remote_server_addr if keep_alive: self._conn = httplib.HTTPConnection( str(addr), str(parsed_url.port), timeout=self._timeout) def _wrap_value(self, value): if isinstance(value, dict): converted = {} for key, val in value.items(): converted[key] = self._wrap_value(val) return converted elif isinstance(value, list): return list(self._wrap_value(item) for item in value) else: return value def _check_response(self, response): if response: self.error_handler.check_response(response) response['value'] = self._unwrap_value( response.get('value', None)) return response # If the server doesn't send a response, assume the command was # a success return {'success': 0, 'value': None, 'sessionId': self.session_id} def _execute(self, path, method, params=None): """ Send a command to the remote server. Any path subtitutions required for the URL mapped to the command should be included in the command parameters. :Args: - command - A string specifying the command to execute. - params - A dictionary of named parameters to send with the command as its JSON payload. """ assert path is not None and method is not None, 'Url Method not None' data = utils.dump_json(params) path = string.Template(path).substitute(params) url = '{0}/{1}'.format(self._url, path) return self._request(method, url, body=data) def get(self, path, params=None): """ Get method :param path: :param params: :return: """ reponse = self._execute(path, Method.GET, params) if reponse: self.error_handler.check_response(reponse) return reponse else: raise RuntimeError("get url error") def post(self, path, params): """ Post method :param path: :param params: :return: """ reponse = self._execute(path, Method.POST, params) if reponse: self.error_handler.check_response(reponse) return reponse return True def _request(self, method, url, body=None): """ Send an HTTP request to the remote server. :Args: - method - A string for the HTTP method to send the request with. - url - A string for the URL to send the request to. - body - A string for request body. Ignored unless method is POST or PUT. :Returns: A dictionary with the server's parsed JSON response. """ LOGGER.debug('%s %s %s' % (method, url, body)) parsed_url = parse.urlparse(url) if self.keep_alive: headers = {"Connection": 'keep-alive', method: parsed_url.path, "User-Agent": "Python http auth", "Content-type": "application/json;charset=\"UTF-8\"", "Accept": "application/json"} if parsed_url.username: auth = base64.standard_b64encode('%s:%s' % (parsed_url.username, parsed_url.password)).replace('\n', '') headers["Authorization"] = "Basic %s" % auth if body and method != 'POST' and method != 'PUT': body = None try: self._conn.request(method, parsed_url.path, body, headers) resp = self._conn.getresponse() except (httplib.HTTPException, socket.error): self._conn.close() raise statuscode = resp.status else: password_manager = None if parsed_url.username: netloc = parsed_url.hostname if parsed_url.port: netloc += ":%s" % parsed_url.port cleaned_url = parse.urlunparse((parsed_url.scheme, netloc, parsed_url.path, parsed_url.params, parsed_url.query, parsed_url.fragment)) password_manager = url_request.HTTPPasswordMgrWithDefaultRealm() password_manager.add_password(None, "%s://%s" % (parsed_url.scheme, netloc), parsed_url.username, parsed_url.password) request = Request(cleaned_url, data=body.encode('utf-8'), method=method) else: request = Request(url, data=body.encode('utf-8'), method=method) request.add_header('Accept', 'application/json') request.add_header('Content-Type', 'application/json;charset=UTF-8') if password_manager: opener = url_request.build_opener(url_request.HTTPRedirectHandler(), HttpErrorHandler(), url_request.HTTPBasicAuthHandler(password_manager)) else: opener = url_request.build_opener(url_request.HTTPRedirectHandler(), HttpErrorHandler()) resp = opener.open(request, timeout=self._timeout) statuscode = resp.code if not hasattr(resp, 'getheader'): if hasattr(resp.headers, 'getheader'): resp.getheader = lambda x: resp.headers.getheader(x) elif hasattr(resp.headers, 'get'): resp.getheader = lambda x: resp.headers.get(x) data = resp.read() try: if 300 <= statuscode < 304: return self._request('GET', resp.getheader('location')) body = data.decode('utf-8').replace('\x00', '').strip() if 399 < statuscode <= 510: return {'status': statuscode, 'value': body} content_type = [] if resp.getheader('Content-Type') is not None: content_type = resp.getheader('Content-Type').split(';') if not any([x.startswith('image/png') for x in content_type]): try: data = utils.load_json(body.strip()) except ValueError: if 199 < statuscode < 300: status = ErrorCode.SUCCESS else: status = ErrorCode.UNKNOWN_ERROR return {'status': status, 'value': body.strip()} assert type(data) is dict, ( 'Invalid server response body: %s' % body) # Some of the drivers incorrectly return a response # with no 'value' field when they should return null. # if 'value' not in data: # data['value'] = None return data else: data = {'status': 0, 'value': body.strip()} return data finally: LOGGER.debug("Finished Request") resp.close()
class ErrorFilter(BaseReader, BaseWriter): """ A filter that gates downstream writers or filters on whether or not any errors have occurred. See :ref:`error-filters` for details. """ temp_path = None def __init__(self, level=logging.ERROR, message='No output as errors have occurred.'): from errorhandler import ErrorHandler self.handler = ErrorHandler(level) self.message = message def start(self, create=True): self.prefix = 0 self.handler.reset() if self.temp_path is not None: rmtree(self.temp_path) if create: self.temp_path = mkdtemp() else: self.temp_path = None BaseWriter.start(self) def get_stream(self, filename): self.prefix += 1 return open( os.path.join(self.temp_path, str(self.prefix) + '-' + filename), 'wb') def get_workbooks(self): if self.temp_path is None: return filenames = [] for name in os.listdir(self.temp_path): d = name.split('-', 1) d.append(name) filenames.append(d) filenames.sort() for i, filename, pathname in filenames: yield ( # We currently don't open with on_demand=True here # as error filters should be lastish in the chain # so there's not much win. # However, if we did, getting rid of the temp dirs # becomes a problem as, on Windows, they can't be # deleted until the xlrd.Book object is done with # and we don't know when that might be :-( xlrd.open_workbook(os.path.join(self.temp_path, pathname), formatting_info=1, on_demand=False, ragged_rows=True), filename) def sheet(self, rdsheet, wtsheet_name): self.rdsheet = rdsheet BaseWriter.sheet(self, rdsheet, wtsheet_name) def cell(self, rdrowx, rdcolx, wtrowx, wtcolx): cell = self.rdsheet.cell(rdrowx, rdcolx) if cell.ctype == xlrd.XL_CELL_EMPTY: return if cell.ctype == xlrd.XL_CELL_ERROR: logger.error("Cell %s of sheet %r contains a bad value: %s" % ( xlrd.cellname(rdrowx, rdcolx), quoted_sheet_name(self.rdsheet.name), cell_display(cell, self.rdbook.datemode), )) return BaseWriter.cell(self, rdrowx, rdcolx, wtrowx, wtcolx) def finish(self): """ The method that triggers downstream filters and writers if no errors have occurred. """ BaseWriter.finish(self) if self.handler.fired: logger.error(self.message) else: self(self.next) self.start(create=False) for attr in ('rdbook', 'rdsheet'): if hasattr(self, attr): delattr(self, attr)
class WebDriver(object): """Controls a browser by sending commands to a remote server. This server is expected to be running the WebDriver wire protocol as defined here: http://code.google.com/p/selenium/wiki/JsonWireProtocol Attributes: command_executor - The command.CommandExecutor object used to execute commands. error_handler - errorhandler.ErrorHandler object used to verify that the server did not return an error. session_id - The session ID to send with every command. capabilities - A dictionary of capabilities of the underlying browser for this instance's session. """ def __init__(self, command_executor, browser_name, platform, version='', javascript_enabled=True): """Create a new driver that will issue commands using the wire protocol. Args: command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. browser_name - A string indicating which browser to request a new session for from the remote server. Should be one of {mobile safari|firefox|internet explorer|htmlunit|chrome}. platform - A string indicating the desired platform to request from the remote server. Should be one of {WINDOWS|XP|VISTA|MAC|LINUX|UNIX|ANY}. version - A string indicating a specific browser version to request, or an empty string ot use any available browser. Defaults to the empty string. javascript_enabled - Whether the requested browser should support JavaScript. Defaults to True. """ self.command_executor = command_executor if type(self.command_executor) is str: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(browser_name=browser_name, platform=platform, version=version, javascript_enabled=javascript_enabled) @property def name(self): """Returns the name of the underlying browser for this instance.""" if 'browserName' in self.capabilities: return self.capabilities['browserName'] else: raise KeyError('browserName not specified in session capabilities') def start_client(self): """Called before starting a new session. This method may be overridden to define custom startup behavior. """ pass def stop_client(self): """Called after executing a quit command. This method may be overridden to define custom shutdown behavior. """ pass def start_session(self, browser_name, platform=None, version=None, javascript_enabled=False): """Creates a new session with the desired capabilities. Args: browser_name: The name of the browser to request. version: Which browser version to request. platform: Which platform to request the browser on. javascript_enabled: Whether the new session should support JavaScript. """ response = self._execute( Command.NEW_SESSION, { 'desiredCapabilities': { 'browserName': browser_name, 'platform': platform or 'ANY', 'version': version or '', 'javascriptEnabled': javascript_enabled } }) self.session_id = response['sessionId'] self.capabilities = response['value'] def _wrap_value(self, value): if isinstance(value, dict): converted = {} for key, val in value.items(): converted[key] = self._wrap_value(val) return converted elif isinstance(value, WebElement): return {'ELEMENT': value.id} elif isinstance(value, list): return list(self._wrap_value(item) for item in value) else: return value def create_web_element(self, element_id): return WebElement(self, element_id) def _unwrap_value(self, value): if isinstance(value, dict) and 'ELEMENT' in value: return self.create_web_element(value['ELEMENT']) elif isinstance(value, list): return list(self._unwrap_value(item) for item in value) else: return value def _execute(self, driver_command, params=None): """Sends a command to be executed by a command.CommandExecutor. Args: driver_command: The name of the command to execute as a string. params: A dictionary of named parameters to send with the command. Returns: The command's JSON response loaded into a dictionary object. """ if not params: params = {'sessionId': self.session_id} elif 'sessionId' not in params: params['sessionId'] = self.session_id params = self._wrap_value(params) response = self.command_executor.execute(driver_command, params) if response: self.error_handler.check_response(response) response['value'] = self._unwrap_value(response.get('value', None)) return response # If the server doesn't send a response, assume the command was # a success return {'success': 0, 'value': None} def get(self, url): """Loads a web page in the current browser.""" self._execute(Command.GET, {'url': url}) def get_title(self): """Gets the title of the current page.""" resp = self._execute(Command.GET_TITLE) return resp['value'] def find_element_by_id(self, id_): """Finds element by id.""" return self._find_element_by("id", id_) def find_elements_by_xpath(self, xpath): """Finds multiple elements by xpath.""" return self._find_elements_by("xpath", xpath) def find_element_by_xpath(self, xpath): """Finds an element by xpath.""" return self._find_element_by("xpath", xpath) def find_element_by_link_text(self, link_text): """Finds an element by its link text.""" return self._find_element_by("link text", link_text) def find_element_by_partial_link_text(self, link_text): """Finds an element by a partial match of its link text.""" return self._find_element_by("partial link text", link_text) def find_elements_by_partial_link_text(self, link_text): """Finds elements by a partial match of their link text.""" return self._find_elements_by("partial link text", link_text) def find_element_by_name(self, name): """Finds an element by its name.""" return self._find_element_by("name", name) def find_elements_by_name(self, name): """Finds elements by their name.""" return self._find_elements_by("name", name) def find_element_by_tag_name(self, name): """Finds an element by its tag name.""" return self._find_element_by("tag name", name) def find_elements_by_tag_name(self, name): """Finds elements by their tag name.""" return self._find_elements_by("tag name", name) def execute_script(self, script, *args): if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self._execute(Command.EXECUTE_SCRIPT, { 'script': script, 'args': converted_args })['value'] def get_current_url(self): """Gets the current url.""" return self._execute(Command.GET_CURRENT_URL)['value'] def get_page_source(self): """Gets the page source.""" return self._execute(Command.GET_PAGE_SOURCE)['value'] def close(self): """Closes the current window.""" self._execute(Command.CLOSE) def quit(self): """Quits the driver and close every associated window.""" try: self._execute(Command.QUIT) finally: self.stop_client() def get_current_window_handle(self): return self._execute(Command.GET_CURRENT_WINDOW_HANDLE)['value'] def get_window_handles(self): return self._execute(Command.GET_WINDOW_HANDLES)['value'] def switch_to_active_element(self): """Returns the element with focus, or BODY if nothing has focus.""" return self._execute(Command.GET_ACTIVE_ELEMENT)['value'] def switch_to_window(self, window_name): """Switches focus to a window.""" self._execute(Command.SWITCH_TO_WINDOW, {'name': window_name}) def switch_to_frame(self, index_or_name): """Switches focus to a frame by index or name.""" self._execute(Command.SWITCH_TO_FRAME, {'id': index_or_name}) def back(self): """Goes back in browser history.""" self._execute(Command.GO_BACK) def forward(self): """Goes forward in browser history.""" self._execute(Command.GO_FORWARD) # Options def get_cookies(self): """Gets all the cookies. Return a set of dicts.""" return self._execute(Command.GET_ALL_COOKIES)['value'] def get_cookie(self, name): """Get a single cookie. Returns the desired cookie dict or None.""" cookies = self.get_cookies() for cookie in cookies: if cookie['name'] == name: return cookie return None def delete_cookie(self, name): """Delete a cookie with the given name.""" self._execute(Command.DELETE_COOKIE, {'name': name}) def delete_all_cookies(self): """Delete all the cookies.""" self._execute(Command.DELETE_ALL_COOKIES) def add_cookie(self, cookie_dict): self._execute(Command.ADD_COOKIE, {'cookie': cookie_dict}) def _find_element_by(self, by, value): return self._execute(Command.FIND_ELEMENT, { 'using': by, 'value': value })['value'] def _find_elements_by(self, by, value): return self._execute(Command.FIND_ELEMENTS, { 'using': by, 'value': value })['value']
class Model(object): """ Base class to all Models """ def __init__(self): self.db_name = current_app.config["DB"]["name"] self.collection_name = "" self.content = None self.error_handle = ErrorHandler() def set_content(self): """ There should be a definition of this function in every child class. This function prepares a dictionary of the child class object's parameters which are to be saved, and set it to self.content """ pass def set_objprops(self, data=None): """ This function should have a definition in a child class for when a single result is expected from the DB query. (when findone=True). Eg: When fetching a user from the DB. This function should then populate the appropriate properties of the object with the data fetched from the DB """ pass def get_db_handler(self): """ Return DB handler for the appropriate collection, returns None if no collection name provided """ if not self.collection_name=="": return MongoClient()[self.db_name][self.collection_name] else: return None def check_duplicate(self, fields): """ provided fields, this function will return true if there is a duplicate entry false if no duplicate value found eg: fields = {"name": "John", "age": 20} """ try: dbh = self.get_db_handler() if dbh.find(fields).count()>0: return True return False except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.Model.check_duplicate()") def get(self, conditions=None, sort_by=[("_id", 1)], distinct=False, distinct_fieldname=None, limit=0, findone=False): """ Return db items fullfilled by conditions, and sorted by ID """ try: dbh = self.get_db_handler() content = None if conditions and "_id" in conditions: if not "noobjectify" in conditions or conditions["noobjectify"]==False: conditions.update({"_id": ObjectId(conditions["_id"])}) if "noobjectify" in conditions: del conditions["noobjectify"] if distinct==True and distinct_fieldname: content = dbh.find(conditions).sort(sort_by).distinct(distinct_fieldname) elif findone==True: content = dbh.find_one(conditions) else: content = dbh.find(conditions).sort(sort_by) if content and limit>0: content = content.limit(limit) return content except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.Model.get()") def save(self, duplicate_fields_check=None, allow_duplicate=False): """ Add a new item to the collection """ try: # duplicate_fields_check should be a dict, with field and its corresponding value self.set_content() if not self.content==None: if allow_duplicate==False and not duplicate_fields_check==None: if self.check_duplicate(fields=duplicate_fields_check)==True: return {"status": "failed", "message": "Could not save item. Duplicate entry found."} dbh = self.get_db_handler() dbh.save(self.content) return {"status": "success", "message": "Successfully added item to the DB"} return {"status": "failed", "message": "Content is empty" } except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.Model.save()") def update(self, conditions={}, overwrite=False, upsert=False, noobjectify=False, multi=False): """ Update a DB entry """ try: self.set_content() dbh = self.get_db_handler() if "_id" in conditions or "_id" in self.content: if not "noobjectify" in conditions or conditions["noobjectify"]==False: if not "_id" in conditions: conditions.update({"_id": ObjectId(self.content["_id"])}) del self.content["_id"] else: conditions.update({"_id": ObjectId(conditions["_id"])}) #remove "noobjectify" from conditions, since it should not be used in update query if "noobjectify" in conditions: del conditions["noobjectify"] if overwrite: dbh.update(conditions, self.content, upsert=upsert, multi=multi) else: dbh.update(conditions, {"$set": self.content}, upsert=upsert, multi=multi) return {"status": "success", "message": "DB item updated successfully."} except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.Model.update()") def remove(self, conditions=None, remove_all=False): """ Remove 1 or more items from the collection """ try: if remove_all==True: conditions = {} elif not conditions==None: if "_id" in conditions: if not "noobjectify" in conditions or conditions["noobjectify"]==False: conditions.update({"_id": ObjectId(conditions["_id"])}) #remove "noobjectify" from conditions, since it should not be used in update query if "noobjectify" in conditions: del conditions["noobjectify"] self.get_db_handler().remove(conditions) return {"status": "success", "message": "Successfully removed item(s) from the DB"} except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.Model.remove()")
class WebDriver(object): """Controls a browser by sending commands to a remote server. This server is expected to be running the WebDriver wire protocol as defined here: http://code.google.com/p/selenium/wiki/JsonWireProtocol Attributes: command_executor - The command.CommandExecutor object used to execute commands. error_handler - errorhandler.ErrorHandler object used to verify that the server did not return an error. session_id - The session ID to send with every command. capabilities - A dictionary of capabilities of the underlying browser for this instance's session. """ def __init__(self, command_executor='http://localhost:4444/wd/hub', desired_capabilities = None, browser_profile=None): """Create a new driver that will issue commands using the wire protocol. Args: command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. desired_capabilities - Dictionary holding predefined values for starting a browser browser_profile: A browser profile directory as a Base64-encoded zip file. Only used if Firefox is requested. """ if desired_capabilities is None: raise WebDriverException(" Desired Capabilities can't be None") self.command_executor = command_executor if type(self.command_executor) is str: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(desired_capabilities, browser_profile) @property def name(self): """Returns the name of the underlying browser for this instance.""" if 'browserName' in self.capabilities: return self.capabilities['browserName'] else: raise KeyError('browserName not specified in session capabilities') def start_client(self): """Called before starting a new session. This method may be overridden to define custom startup behavior. """ pass def stop_client(self): """Called after executing a quit command. This method may be overridden to define custom shutdown behavior. """ pass def start_session(self, desired_capabilities, browser_profile=None): """Creates a new session with the desired capabilities. Args: browser_name: The name of the browser to request. version: Which browser version to request. platform: Which platform to request the browser on. javascript_enabled: Whether the new session should support JavaScript. browser_profile: A browser profile directory as a Base64-encoded zip file. Only used if Firefox is requested. """ if browser_profile: desired_capabilities['firefox_profile'] = browser_profile response = self.execute(Command.NEW_SESSION, { 'desiredCapabilities': desired_capabilities }) self.session_id = response['sessionId'] self.capabilities = response['value'] def _wrap_value(self, value): if isinstance(value, dict): converted = {} for key, val in value.items(): converted[key] = self._wrap_value(val) return converted elif isinstance(value, WebElement): return {'ELEMENT': value.id} elif isinstance(value, list): return list(self._wrap_value(item) for item in value) else: return value def create_web_element(self, element_id): return WebElement(self, element_id) def _unwrap_value(self, value): if isinstance(value, dict) and 'ELEMENT' in value: return self.create_web_element(value['ELEMENT']) elif isinstance(value, list): return list(self._unwrap_value(item) for item in value) else: return value def execute(self, driver_command, params=None): """Sends a command to be executed by a command.CommandExecutor. Args: driver_command: The name of the command to execute as a string. params: A dictionary of named parameters to send with the command. Returns: The command's JSON response loaded into a dictionary object. """ if not params: params = {'sessionId': self.session_id} elif 'sessionId' not in params: params['sessionId'] = self.session_id params = self._wrap_value(params) response = self.command_executor.execute(driver_command, params) if response: self.error_handler.check_response(response) response['value'] = self._unwrap_value( response.get('value', None)) return response # If the server doesn't send a response, assume the command was # a success return {'success': 0, 'value': None} def get(self, url): """Loads a web page in the current browser.""" self.execute(Command.GET, {'url': url}) @property def title(self): """Gets the title of the current page.""" resp = self.execute(Command.GET_TITLE) return resp['value'] if resp['value'] is not None else "" def find_element_by_id(self, id_): """Finds element by id.""" return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_): """Finds element by id.""" return self.find_elements(by=By.ID, value=id_) def find_elements_by_xpath(self, xpath): """Finds multiple elements by xpath.""" return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_xpath(self, xpath): """Finds an element by xpath.""" return self.find_element(by=By.XPATH, value=xpath) def find_element_by_link_text(self, link_text): """Finds an element by its link text.""" return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, link_text): """Finds elements by their link text.""" return self.find_elements(by=By.LINK_TEXT, value=link_text) def find_element_by_partial_link_text(self, link_text): """Finds an element by a partial match of its link text.""" return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text): """Finds elements by a partial match of their link text.""" return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_name(self, name): """Finds an element by its name.""" return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name): """Finds elements by their name.""" return self.find_elements(by=By.NAME, value=name) def find_element_by_tag_name(self, name): """Finds an element by its tag name.""" return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name): """Finds elements by their tag name.""" return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_class_name(self, name): """Finds an element by their class name.""" return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name): """Finds elements by their class name.""" return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector): """Find and return an element by CSS selector.""" return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector): """Find and return list of multiple elements by CSS selector.""" return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def execute_script(self, script, *args): if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute( Command.EXECUTE_SCRIPT, {'script': script, 'args':converted_args})['value'] def execute_async_script(self, script, *args): if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute( Command.EXECUTE_ASYNC_SCRIPT, {'script': script, 'args':converted_args})['value'] @property def current_url(self): """Gets the current url.""" return self.execute(Command.GET_CURRENT_URL)['value'] def get_page_source(self): """Gets the page source.""" return self.execute(Command.GET_PAGE_SOURCE)['value'] def close(self): """Closes the current window.""" self.execute(Command.CLOSE) def quit(self): """Quits the driver and close every associated window.""" try: self.execute(Command.QUIT) finally: self.stop_client() def get_current_window_handle(self): return self.execute(Command.GET_CURRENT_WINDOW_HANDLE)['value'] def get_window_handles(self): return self.execute(Command.GET_WINDOW_HANDLES)['value'] #Target Locators def switch_to_active_element(self): """Returns the element with focus, or BODY if nothing has focus.""" return self.execute(Command.GET_ACTIVE_ELEMENT)['value'] def switch_to_window(self, window_name): """Switches focus to a window.""" self.execute(Command.SWITCH_TO_WINDOW, {'name': window_name}) def switch_to_frame(self, index_or_name): """Switches focus to a frame by index or name.""" self.execute(Command.SWITCH_TO_FRAME, {'id': index_or_name}) def switch_to_default_content(self): """Switch to the default frame""" self.execute(Command.SWITCH_TO_FRAME, {'id': None}) def switch_to_alert(self): """ Switch to the alert on the page """ return Alert(self) #Navigation def back(self): """Goes back in browser history.""" self.execute(Command.GO_BACK) def forward(self): """Goes forward in browser history.""" self.execute(Command.GO_FORWARD) def refresh(self): """Refreshes the current page.""" self.execute(Command.REFRESH) # Options def get_cookies(self): """Gets all the cookies. Return a set of dicts.""" return self.execute(Command.GET_ALL_COOKIES)['value'] def get_cookie(self, name): """Get a single cookie. Returns the desired cookie dict or None.""" cookies = self.get_cookies() for cookie in cookies: if cookie['name'] == name: return cookie return None def delete_cookie(self, name): """Delete a cookie with the given name.""" self.execute(Command.DELETE_COOKIE, {'name': name}) def delete_all_cookies(self): """Delete all the cookies.""" self.execute(Command.DELETE_ALL_COOKIES) def add_cookie(self, cookie_dict): self.execute(Command.ADD_COOKIE, {'cookie': cookie_dict}) # Timeouts def implicitly_wait(self, time_to_wait): """Set the implicit time out for use by later actions """ self.execute(Command.IMPLICIT_WAIT, {'ms': time_to_wait*1000}) def set_script_timeout(self, time_to_wait): """Set the timeout that the script should wait before throwing an error""" self.execute(Command.SET_SCRIPT_TIMEOUT, {'ms': time_to_wait*1000}) def find_element(self, by=By.ID, value=None): return self.execute(Command.FIND_ELEMENT, {'using': by, 'value': value})['value'] def find_elements(self, by=By.ID, value=None): return self.execute(Command.FIND_ELEMENTS, {'using': by, 'value': value})['value'] def get_screenshot_as_file(self, filename): """Gets the screenshot of the current window. Returns False if there is any IOError, else returns True. Use full paths in your filename.""" png = self.execute(Command.SCREENSHOT)['value'] try: f = open(filename, 'wb') f.write(base64.decodestring(png)) f.close() except IOError: return False finally: del png return True def get_screenshot_as_base64(self): """Gets the screenshot of the current window as a base64 encoded string which is useful in embedded images in HTML.""" return self.execute(Command.SCREENSHOT)['value']
class WebDriver(object): """Controls a browser by sending commands to a remote server. This server is expected to be running the WebDriver wire protocol as defined here: http://code.google.com/p/selenium/wiki/JsonWireProtocol Attributes: command_executor - The command.CommandExecutor object used to execute commands. error_handler - errorhandler.ErrorHandler object used to verify that the server did not return an error. session_id - The session ID to send with every command. capabilities - A dictionary of capabilities of the underlying browser for this instance's session.""" def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities=None, browser_profile=None): """Create a new driver that will issue commands using the wire protocol. Args: command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to. desired_capabilities - Dictionary holding predefined values for starting a browser browser_profile: A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. """ if desired_capabilities is None: raise WebDriverException("Desired Capabilities can't be None") self.command_executor = command_executor if type(self.command_executor) is str: self.command_executor = RemoteConnection(command_executor) self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(desired_capabilities, browser_profile) @property def name(self): """Returns the name of the underlying browser for this instance. Usage: driver.name """ if 'browserName' in self.capabilities: return self.capabilities['browserName'] else: raise KeyError('browserName not specified in session capabilities') def start_client(self): """Called before starting a new session. This method may be overridden to define custom startup behavior.""" pass def stop_client(self): """Called after executing a quit command. This method may be overridden to define custom shutdown behavior.""" pass def start_session(self, desired_capabilities, browser_profile=None): """Creates a new session with the desired capabilities. Args: browser_name: The name of the browser to request. version: Which browser version to request. platform: Which platform to request the browser on. javascript_enabled: Whether the new session should support JavaScript. browser_profile: A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. """ if browser_profile: desired_capabilities['firefox_profile'] = browser_profile.encoded response = self.execute(Command.NEW_SESSION, { 'desiredCapabilities': desired_capabilities, }) self.session_id = response['sessionId'] self.capabilities = response['value'] def _wrap_value(self, value): if isinstance(value, dict): converted = {} for key, val in value.items(): converted[key] = self._wrap_value(val) return converted elif isinstance(value, WebElement): return {'ELEMENT': value.id} elif isinstance(value, list): return list(self._wrap_value(item) for item in value) else: return value def create_web_element(self, element_id): """Creates a web element with the specified element_id.""" return WebElement(self, element_id) def _unwrap_value(self, value): if isinstance(value, dict) and 'ELEMENT' in value: return self.create_web_element(value['ELEMENT']) elif isinstance(value, list): return list(self._unwrap_value(item) for item in value) else: return value def execute(self, driver_command, params=None): """Sends a command to be executed by a command.CommandExecutor. Args: driver_command: The name of the command to execute as a string. params: A dictionary of named parameters to send with the command. Returns: The command's JSON response loaded into a dictionary object. """ if not params: params = {'sessionId': self.session_id} elif 'sessionId' not in params: params['sessionId'] = self.session_id params = self._wrap_value(params) response = self.command_executor.execute(driver_command, params) if response: self.error_handler.check_response(response) response['value'] = self._unwrap_value(response.get('value', None)) return response # If the server doesn't send a response, assume the command was # a success return {'success': 0, 'value': None, 'sessionId': self.session_id} def get(self, url): """Loads a web page in the current browser session.""" self.execute(Command.GET, {'url': url}) @property def title(self): """Returns the title of the current page. Usage: driver.title """ resp = self.execute(Command.GET_TITLE) return resp['value'] if resp['value'] is not None else "" def find_element_by_id(self, id_): """Finds an element by id. Args: id_: The id of the element to be found. Usage: driver.find_element_by_id('foo') """ return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_): """Finds multiple elements by id. Args: id_: The id of the elements to be found. Usage: driver.find_element_by_id('foo') """ return self.find_elements(by=By.ID, value=id_) def find_element_by_xpath(self, xpath): """Finds an element by xpath. Args: xpath: The xpath locator of the element to find. Usage: driver.find_element_by_xpath('//div/td[1]') """ return self.find_element(by=By.XPATH, value=xpath) def find_elements_by_xpath(self, xpath): """Finds multiple elements by xpath. Args: xpath: The xpath locator of the elements to be found. Usage: driver.find_elements_by_xpath("//div[contains(@class, 'foo')]") """ return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_link_text(self, link_text): """Finds an element by link text. Args: link_text: The text of the element to be found. Usage: driver.find_element_by_link_text('Sign In') """ return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, text): """Finds elements by link text. Args: link_text: The text of the elements to be found. Usage: driver.find_elements_by_link_text('Sign In') """ return self.find_elements(by=By.LINK_TEXT, value=text) def find_element_by_partial_link_text(self, link_text): """Finds an element by a partial match of its link text. Args: link_text: The text of the element to partially match on. Usage: driver.find_element_by_partial_link_text('Sign') """ return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text): """Finds elements by a partial match of their link text. Args: link_text: The text of the element to partial match on. Usage: driver.find_element_by_partial_link_text('Sign') """ return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_name(self, name): """Finds an element by name. Args: name: The name of the element to find. Usage: driver.find_element_by_name('foo') """ return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name): """Finds elements by name. Args: name: The name of the elements to find. Usage: driver.find_elements_by_name('foo') """ return self.find_elements(by=By.NAME, value=name) def find_element_by_tag_name(self, name): """Finds an element by tag name. Args: name: The tag name of the element to find. Usage: driver.find_element_by_tag_name('foo') """ return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name): """Finds elements by tag name. Args: name: The tag name the use when finding elements. Usage: driver.find_elements_by_tag_name('foo') """ return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_class_name(self, name): """Finds an element by class name. Args: name: The class name of the element to find. Usage: driver.find_element_by_class_name('foo') """ return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name): """Finds elements by class name. Args: name: The class name of the elements to find. Usage: driver.find_elements_by_class_name('foo') """ return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector): """Finds an element by css selector. Args: css_selector: The css selector to use when finding elements. Usage: driver.find_element_by_css_selector('#foo') """ return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector): """Finds elements by css selector. Args: css_selector: The css selector to use when finding elements. Usage: driver.find_element_by_css_selector('#foo') """ return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def execute_script(self, script, *args): """Synchronously Executes JavaScript in the current window/frame. Args: script: The JavaScript to execute. *args: Any applicable arguments for your JavaScript. Usage: driver.execute_script('document.title') """ if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute(Command.EXECUTE_SCRIPT, { 'script': script, 'args': converted_args })['value'] def execute_async_script(self, script, *args): """Asynchronously Executes JavaScript in the current window/frame. Args: script: The JavaScript to execute. args: Any applicable arguments for your JavaScript. Usage: driver.execute_async_script('document.title') """ if len(args) == 1: converted_args = args[0] else: converted_args = list(args) converted_args = list(args) return self.execute(Command.EXECUTE_ASYNC_SCRIPT, { 'script': script, 'args': converted_args })['value'] @property def current_url(self): """Gets the URL of the current page. Usage: driver.current_url """ return self.execute(Command.GET_CURRENT_URL)['value'] @property def page_source(self): """Gets the source of the current page. Usage: driver.page_source """ return self.execute(Command.GET_PAGE_SOURCE)['value'] def close(self): """Closes the current window. Usage: driver.close() """ self.execute(Command.CLOSE) def quit(self): """Quits the driver and closes every associated window. Usage: driver.quit() """ try: self.execute(Command.QUIT) finally: self.stop_client() @property def current_window_handle(self): """Returns the handle of the current window. Usage: driver.current_window_handle """ return self.execute(Command.GET_CURRENT_WINDOW_HANDLE)['value'] @property def window_handles(self): """Returns the handles of all windows within the current session. Usage: driver.window_handles """ return self.execute(Command.GET_WINDOW_HANDLES)['value'] #Target Locators def switch_to_active_element(self): """Returns the element with focus, or BODY if nothing has focus. Usage: driver.switch_to_active_element() """ return self.execute(Command.GET_ACTIVE_ELEMENT)['value'] def switch_to_window(self, window_name): """Switches focus to the specified window. Args: window_name: The name of the window to switch to. Usage: driver.switch_to_window('main') """ self.execute(Command.SWITCH_TO_WINDOW, {'name': window_name}) def switch_to_frame(self, index_or_name): """Switches focus to the specified frame, by index or name. Args: index_or_name: The name of the window to switch to, or an integer representing the index to switch to. Usage: driver.switch_to_frame('frame_name') driver.switch_to_frame(1) """ self.execute(Command.SWITCH_TO_FRAME, {'id': index_or_name}) def switch_to_default_content(self): """Switch focus to the default frame. Usage: driver.switch_to_default_content() """ self.execute(Command.SWITCH_TO_FRAME, {'id': None}) def switch_to_alert(self): """Switches focus to an alert on the page. Usage: driver.switch_to_alert() """ return Alert(self) #Navigation def back(self): """Goes one step backward in the browser history. Usage: driver.back() """ self.execute(Command.GO_BACK) def forward(self): """Goes one step forward in the browser history. Usage: driver.forward() """ self.execute(Command.GO_FORWARD) def refresh(self): """Refreshes the current page. Usage: driver.refresh() """ self.execute(Command.REFRESH) # Options def get_cookies(self): """Returns a set of dictionaries, corresponding to cookies visible in the current session. Usage: driver.get_cookies() """ return self.execute(Command.GET_ALL_COOKIES)['value'] def get_cookie(self, name): """Get a single cookie by name. Returns the cookie if found, None if not. Usage: driver.get_cookie('my_cookie') """ cookies = self.get_cookies() for cookie in cookies: if cookie['name'] == name: return cookie return None def delete_cookie(self, name): """Deletes a single cookie with the given name. Usage: driver.delete_cookie('my_cookie') """ self.execute(Command.DELETE_COOKIE, {'name': name}) def delete_all_cookies(self): """Delete all cookies in the scope of the session. Usage: driver.delete_all_cookies() """ self.execute(Command.DELETE_ALL_COOKIES) def add_cookie(self, cookie_dict): """Adds a cookie to your current session. Args: cookie_dict: A dictionary object, with the desired cookie name as the key, and the value being the desired contents. Usage: driver.add_cookie({'foo': 'bar',}) """ self.execute(Command.ADD_COOKIE, {'cookie': cookie_dict}) # Timeouts def implicitly_wait(self, time_to_wait): """Sets a sticky timeout to implicitly wait for an element to be found, or a command to complete. This method only needs to be called one time per session. Args: time_to_wait: Amount of time to wait Usage: driver.implicitly_wait(30) """ self.execute(Command.IMPLICIT_WAIT, {'ms': float(time_to_wait) * 1000}) def set_script_timeout(self, time_to_wait): """Set the amount of time that the script should wait before throwing an error. Args: time_to_wait: The amount of time to wait Usage: driver.set_script_timeout(30) """ self.execute(Command.SET_SCRIPT_TIMEOUT, {'ms': float(time_to_wait) * 1000}) def find_element(self, by=By.ID, value=None): """'Private' method used by the find_element_by_* methods. Usage: Use the corresponding find_element_by_* instead of this. """ return self.execute(Command.FIND_ELEMENT, { 'using': by, 'value': value })['value'] def find_elements(self, by=By.ID, value=None): """'Private' method used by the find_elements_by_* methods. Usage: Use the corresponding find_elements_by_* instead of this. """ return self.execute(Command.FIND_ELEMENTS, { 'using': by, 'value': value })['value'] @property def desired_capabilities(self): """ returns the drivers current desired capabilities being used""" return self.capabilities def get_screenshot_as_file(self, filename): """Gets the screenshot of the current window. Returns False if there is any IOError, else returns True. Use full paths in your filename. Args: filename: The full path you wish to save your screenshot to. Usage: driver.get_screenshot_as_file('/Screenshots/foo.png') """ png = self.execute(Command.SCREENSHOT)['value'] try: with open(filename, 'wb') as f: f.write(base64.decodestring(png)) except IOError: return False del png return True def get_screenshot_as_base64(self): """Gets the screenshot of the current window as a base64 encoded string which is useful in embedded images in HTML. Usage: driver.get_screenshot_as_base64() """ return self.execute(Command.SCREENSHOT)['value']
class Plugin: is_active = False url_for = url_for error_handle = ErrorHandler() template = Environment(loader=FileSystemLoader(current_app.config["PLUGINS_PATH"])) admin_role = "admin" available_roles = ["anon", "viewer", "buyer", "subscriber", "provider", admin_role] required_roles = [] # set in each module def __init__(self): self.required_roles = [] # set in each module def activate(self): """Activate this plugin""" if self.is_active==False: self.is_active = True self.main() def deactivate(self): """Deactivate this plugin""" if self.is_active==True: self.is_active = False def main(self): """ This is the entry point of plugin functions. All plugin activities should be within main function. It'll be called right after "activating" the plugin. Also, after "save_settings" and "save data". """ pass def reload(self): """ This function will by default call the main function. It'll be called after saving settings, or inserting new data. This is to prevent """ self.main() def save_settings(self, settings, user_specific=True, overwrite=False): """ This function saves any settings specific to a plugin """ try: PSM = PluginSettingsModel(plugin_id=self.id) if overwrite==False: PSM.settings = self.get_settings() if PSM.settings: PSM.settings.update(settings) else: PSM.settings = settings conditions = {"plugin_id": PSM.plugin_id} if user_specific: conditions.update({"user_id": current_user.get_userid()}) PSM.update(conditions=conditions, upsert=True, overwrite=overwrite) self.reload() except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.plugin.save_settings()") def get_settings(self, user_specific=True): """ This function returns the settings stored by the plugin """ try: PSM = PluginSettingsModel(plugin_id=self.id) settings = None conditions = {"plugin_id": PSM.plugin_id} if user_specific: conditions.update({"user_id": current_user.get_userid()}) result = PSM.get(conditions=conditions, findone=True) if result: settings = result["settings"] return settings except Exception as e: self.error_handle.get_error(error=str(e), occurred_at="mad.lib.plugin.get_settings()") return None def save_data(self, data=None, conditions={}, upsert=False, user_specific=True, update=False, allow_duplicate=False, dup_fields=None): """ This function is used to save/insert/update data, specific to a plugin data : data to be saved conditions: conditions, in case data is being updated upsert : if data is to be upserted """ try: if user_specific: data.update({"user_id": current_user.get_userid()}) PDM = PluginDataModel(plugin_id=self.id) PDM.data = data status = None if update: status = PDM.update(conditions=conditions, upsert=upsert) else: dup_fields.update({"plugin_id": PDM.plugin_id}) status = PDM.save(allow_duplicate=allow_duplicate, duplicate_fields_check=dup_fields) self.reload() return status except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.plugin.save_data()") def get_data(self, conditions=None, sort_by=[("_id", 1)], distinct=False, distinct_fieldname=None, user_specific=True): """ This function is used to retrieve data stored by the pliugin based on the condition provided """ try: PDM = PluginDataModel(plugin_id=self.id) if not conditions: conditions = {} conditions.update({"plugin_id": PDM.plugin_id}) if user_specific: conditions.update({"user_id": current_user.get_userid()}) if distinct==True: return PDM.get(conditions=conditions, sort_by=sort_by, distinct=True, distinct_fieldname=distinct_fieldname) else: return PDM.get(conditions=conditions, sort_by=sort_by) except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.plugin.get_data()") def plugin_home(self): """This function should return HTML for the plugin's home page""" html = ( '<h2 class="title">Plugin Home</h2>' '<p>Hello, this is your plugin homepage</p>' ) return html def plugin_settings(self): """ This function should return HTML for the plugin's settings page. """ html = ( '<h2 class="title">Plugin Settings</h2>' '<p>Display all your plugin settings here.</p>' ) return html def public_content(self, form=None, params=None): """ This function should return HTML for any public facing content the plugin wants to push""" return None def check_role(self): """ Check if the current user has the required role to access this view. If the function returns: True : User has the required role/permission to access this page. False: User does not have required role/permission to access this page. Available roles: anon - not logged in user viewer - is the default role of a logged in user. provider - Ad space provider, who will have access to add their media to the system. buyer - Consumer looking for ad spaces, has access to the search module. subscriber - A subscribed user """ if not self.required_roles or not self.available_roles: return True elif current_user.is_authenticated(): current_user_role = current_user.get_role() if current_user_role in self.available_roles: if current_user_role==self.admin_role or current_user_role in self.required_roles: return True return False def render_plugin(self, template_src=None, data=None): """ Render html""" try: if not self.check_role(): abort(403) if not data or not type(data)==dict: data = {} data.update({"current_user": current_user}) data.update({"url_for": url_for}) data.update({"plugin_id": self.id}) args = Struct(**data) return self.template.get_template(template_src).render(data=args) except Exception as e: return self.error_handle.get_error(error=str(e), occurred_at="mad.lib.plugin.render_plugin()")
def __init__(self, level=logging.ERROR, message="No output as errors have occurred."): from errorhandler import ErrorHandler self.handler = ErrorHandler(level) self.message = message
def _main(): """pyznap main function. Parses arguments and calls snap/clean/send functions accordingly. Returns ------- int Exit code """ settings = { "matching": None, } parser = ArgumentParser( prog='pyznap', description='ZFS snapshot tool written in python (version=' + __version__ + ')') parser.add_argument('-q', '--quiet', action="store_true", dest="quiet", help='quiet logging, only errors shown (WARNING)') parser.add_argument('-v', '--verbose', action="store_true", dest="verbose", help='print more verbose output (DEBUG)') parser.add_argument('-t', '--trace', action="store_true", dest="trace", help='print run tracing output (TRACE)') parser.add_argument('-n', '--dry-run', action="store_true", dest="dry_run", help='only test run, no action taken') parser.add_argument('--syslog', action="store_true", dest="syslog", help='add logging to syslog (INFO)') parser.add_argument('--logconfig', action="store_true", dest="logconfig", help='add config name to log') parser.add_argument('--config', action="store", dest="config", help='path to config file') parser.add_argument('-m', '--matching', action="store", dest="matching", help='only process matching filesystems') parser.add_argument('--pidfile', action="store", dest="pidfile", default=None, help='path to pid file') parser.add_argument('-V', '--version', action="store_true", dest="version", help='print version number') subparsers = parser.add_subparsers(dest='command') parser_setup = subparsers.add_parser('setup', help='initial setup') parser_setup.add_argument( '-p', '--path', action='store', dest='path', help='pyznap config dir. default is {:s}'.format(CONFIG_DIR)) parser_snap = subparsers.add_parser('snap', help='zfs snapshot tools') parser_snap.add_argument('--take', action="store_true", help='take snapshots according to config file') parser_snap.add_argument( '--clean', action="store_true", help='clean old snapshots according to config file') parser_snap.add_argument( '--full', action="store_true", help='take snapshots then clean old according to config file') parser_send = subparsers.add_parser('send', help='zfs send/receive tools') parser_send.add_argument('-s', '--source', action="store", dest='source', help='source filesystem') parser_send.add_argument('-d', '--dest', action="store", dest='dest', help='destination filesystem') parser_send.add_argument('-i', '--key', action="store", dest='key', help='ssh key if only source or dest is remote') parser_send.add_argument('-j', '--source-key', action="store", dest='source_key', help='ssh key for source if both are remote') parser_send.add_argument('-k', '--dest-key', action="store", dest='dest_key', help='ssh key for dest if both are remote') parser_send.add_argument( '-c', '--compress', action="store", dest='compress', help='compression to use for ssh transfer. default is lzop') parser_send.add_argument('-e', '--exclude', nargs='+', dest='exclude', help='datasets to exclude') parser_send.add_argument('-w', '--raw', action="store_true", dest='raw', help='raw zfs send. default is false') parser_send.add_argument('-r', '--resume', action="store_true", dest='resume', help='resumable send. default is false') parser_send.add_argument('-l', '--last', action="store_true", dest='send_last_snapshot', help='stat sending from last snapshot') parser_send.add_argument( '--dest-auto-create', action="store_true", dest='dest_auto_create', help='create destination if it does not exist. default is false') parser_send.add_argument('--retries', action="store", type=int, dest='retries', default=0, help='number of retries on error. default is 0') parser_send.add_argument( '--retry-interval', action="store", type=int, dest='retry_interval', default=10, help='interval in seconds between retries. default is 10') parser_send.add_argument( '--max-depth', action="store", type=int, dest='max_depth', help= 'define max depth for child recursion (0 no child, default infinite depth)' ) parser_fix = subparsers.add_parser( 'fix', help='fix zfs snapshot from other format to pyznap') parser_fix.add_argument('-t', '--type', action="store", dest='type', help='snapshot type name') parser_fix.add_argument( '-f', '--format', action="store", required=True, dest='format', help= 'snapshot format specification (regexp/@predefined[@zfs-auto-snap,@zfsnap])' ) parser_fix.add_argument('-m', '--map', action="store", dest='map', help='optional type mapping (old=new:...)') parser_fix.add_argument('-r', '--recurse', action="store_true", dest='recurse', help='recurse in child filesystems') # TODO: time shift parser_fix.add_argument('filesystem', nargs='+', help='filesystems to fix') subparsers.add_parser('full', help='full cycle: snap --take / send / snap --clean') parser_status = subparsers.add_parser( 'status', help='check filesystem snapshots status') parser_status.add_argument('--format', action="store", default='log', choices=['log', 'jsonl', 'html'], dest='status_format', help='status output format') parser_status.add_argument('--all', action="store_true", dest='status_all', help='show all ZFS filesystems') parser_status.add_argument('--print-config', action="store_true", dest='print_config', help='only print parsed and processed config') parser_status.add_argument('--values', action="store", dest='values', help='coma separated values to print') parser_status.add_argument('--filter', action="append", dest='filter_values', help='add filter for col=value') parser_status.add_argument('--exclude', action="append", dest='filter_exclude', help='exclude name filesystems (fnmatch)') if len(sys.argv) == 1: parser.print_help(sys.stderr) sys.exit(1) args = parser.parse_args() if args.version: print(__version__) sys.exit() if not args.command: print('ERROR: No command specified.\n') parser.print_help(sys.stderr) sys.exit(1) e = ErrorHandler() loglevel = logging.INFO if args.quiet: loglevel = logging.WARNING if args.verbose: loglevel = logging.DEBUG if args.command == 'status' and args.status_format != 'log': # for raw status only error show loglevel = logging.ERROR if args.trace: # trace override all logging.addLevelName(8, 'TRACE') loglevel = 8 basicloglevel = min(loglevel, logging.INFO) if args.syslog else loglevel # logging.basicConfig(level=basicloglevel) root_logger = logging.getLogger() root_logger.setLevel(basicloglevel) config_path = args.config if args.config else os.path.join( CONFIG_DIR, 'pyznap.conf') logadd = ' #' + config_path if args.logconfig else '' console_fmt = logging.Formatter('%(asctime)s %(levelname)s: %(message)s' + logadd, datefmt='%b %d %H:%M:%S') if loglevel < logging.WARNING: console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(console_fmt) console_handler.addFilter( lambda record: record.levelno < 30 ) # logging.WARNING make exception in destroy console_handler.setLevel(loglevel) root_logger.addHandler(console_handler) console_err_handler = logging.StreamHandler(sys.stderr) console_err_handler.setFormatter(console_fmt) console_err_handler.setLevel(logging.WARNING) root_logger.addHandler(console_err_handler) if args.syslog: # setup logging to syslog syslog_handler = logging.handlers.SysLogHandler( address='/dev/log', facility=logging.handlers.SysLogHandler.LOG_DAEMON) syslog_handler.setFormatter( logging.Formatter('pyznap: [%(levelname)s] %(message)s' + logadd)) # syslog always level INFO syslog_handler.setLevel(logging.INFO) root_logger.addHandler(syslog_handler) logger = logging.getLogger(__name__) if args.dry_run: set_dry_run() if args.matching: settings['matching'] = args.matching if args.pidfile is not None: if not check_pid(args.pidfile): logger.info('pidfile {} exists, exiting'.format(args.pidfile)) sys.exit(1) open(args.pidfile, "w").write("{}\n".format(os.getpid())) try: logger.info('Starting pyznap...') if args.command in ('snap', 'send', 'full', 'status'): logger.info('Read config={}'.format(config_path)) config = read_config(config_path) if config == None: return 1 if args.command == 'setup': path = args.path if args.path else CONFIG_DIR create_config(path) elif args.command == 'full': take_config(config, settings) send_config(config, settings) clean_config(config, settings) elif args.command == 'snap': # Default if no args are given if not args.take and not args.clean: args.full = True if args.take or args.full: take_config(config, settings) if args.clean or args.full: clean_config(config, settings) elif args.command == 'send': if args.source and args.dest: # use args.key if either source or dest is remote source_key, dest_key = None, None if args.dest.startswith('ssh'): dest_key = [args.key] if args.key else None elif args.source.startswith('ssh'): source_key = args.key if args.key else None # if source_key and dest_key are given, overwrite previous value source_key = args.source_key if args.source_key else source_key dest_key = [args.dest_key] if args.dest_key else dest_key # get exclude rules exclude = [args.exclude] if args.exclude else None # check if raw send was requested raw = [args.raw] if args.raw else None # compress ssh zfs send/receive compress = [args.compress] if args.compress else None # use receive resume token resume = [args.resume] if args.resume else None # retry zfs send/receive retries = [args.retries] if args.retries else None # wait interval for retry retry_interval = [args.retry_interval ] if args.retry_interval else None # automatically create dest dataset if it does not exist dest_auto_create = [args.dest_auto_create ] if args.dest_auto_create else None # start send from last snapshot send_last_snapshot = [args.send_last_snapshot ] if args.send_last_snapshot else None send_config([{ 'name': args.source, 'dest': [args.dest], 'key': source_key, 'dest_keys': dest_key, 'compress': compress, 'exclude': exclude, 'raw_send': raw, 'resume': resume, 'dest_auto_create': dest_auto_create, 'retries': retries, 'retry_interval': retry_interval, 'max_depth': args.max_depth, 'send_last_snapshot': send_last_snapshot }]) elif args.source and not args.dest: logger.error('Missing dest...') elif args.dest and not args.source: logger.error('Missing source...') else: send_config(config, settings) elif args.command == 'fix': tmap = args.map if tmap: tmap = dict(kw.split('=') for kw in args.map.split(':')) fix_snapshots(args.filesystem, format=args.format, type=args.type, recurse=args.recurse, type_map=tmap) elif args.command == 'status': if args.print_config: print(str(config)) else: filter_values = None if args.filter_values: filter_values = {} for fv in args.filter_values: f, v = fv.split('=') v = {'true': True, 'false': False}.get(v.lower(), v) filter_values[f] = v status_config(config, output=args.status_format, show_all=args.status_all, values=tuple(args.values.split(',')) if args.values else None, filter_values=filter_values, filter_exclude=args.filter_exclude, settings=settings) zfs.STATS.log() logger.info('Finished successfully...') finally: if args.pidfile is not None: os.unlink(args.pidfile) return 1 if e.fired else 0