将变量注入函数;蟒蛇

时间:2016-02-22 17:44:21

标签: python python-3.x selenium selenium-webdriver python-decorators

我有一个webdriver类,假设只有一个驱动程序。这很糟糕,因为它无法一次处理多个页面。我想制作一个装饰器,它将self.driver注入任何装饰的函数(如果它存在),否则它将允许任何函数使用传递给它的驱动程序。我应该能够定义和运作

@get_driver
def this_func(**kwargs):
    #I have access to 'driver' if I have self.driver or if a driver kwarg was given

这是:

import os, time, subprocess, random

from functools import wraps

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.select import Select

from pyvirtualdisplay import Display

class get_driver(object):

    def __init__(self, func):
        self.func = func
        wraps(func)(self)

    def __call__(self, *args, **kwargs):

        try:
            kwargs.update({'driver': self.driver})
        except:
            pass
        return_ = self.func(*args, **kwargs)
        return return_

class WebdriverChauffuer(object):

    def __init__(self, username=None, password=None, start_url=None):
        self.username = username
        self.password = password
        self.start_url = start_url

    @get_driver
    def source_code(self, **kwargs):
        return driver.page_source or None

class FirefoxDriver(WebdriverChauffuer):

    def __init__(self, username=None, password=None, start_url=None, driver=None):
        super(FirefoxDriver, self).__init__(username=username, password=password, start_url=start_url)

    def start_driver(self):
        self.driver = webdriver.Firefox()

我收到一个奇怪的错误,即没有给出args,即使我在一个实例上调用source_code,这应该是自己的:

In [1]: from my_scripting_library import *

In [2]: d = FirefoxDriver()

In [3]: d.start
d.start_driver  d.start_url     

In [3]: d.start_driver()

In [4]: d.get('https://google.com')

In [5]: d.source_code()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-7419cf5df019> in <module>()
----> 1 d.source_code()

/home/cchilders/scripts/my_scripting_library/webdriver/general.pyc in __call__(self, *args, **kwargs)
     24         except:
     25             pass
---> 26         return_ = self.func(*args, **kwargs)
     27         return return_
     28 

TypeError: source_code() takes exactly 1 argument (0 given)

当我将回报更改为

时没有区别
return_ = self.func(**kwargs)

为什么我不能再打电话给source_code了?谢谢

编辑:

这些驱动程序当然是用于目的,这里是一个例子:

class HCCDriver(FirefoxDriver):

    def __init__(self, init=False):
        super(HCCDriver, self).__init__(start_url="https://hccadvisor.hccfl.edu")

    def main_page(self):
        self.get('https://www.hccfl.edu/hawknet.aspx')

    def login_webadvisor(self, username="cchilders", password="miley_cirus_is_great_singer", driver=None):
        self.webadvisor_driver = FirefoxDriver()
        webadvisor_driver.get(self.start_url)
        time.sleep(2)
        driver.access_link(search_text="Log In")
        driver.find_box_and_fill(search_text="LABELID_USER_NAME", value=username)
        driver.find_box_and_fill(search_text="CURR.PWD", value=password)
        driver.submit_form(search_text="SUBMIT")
        driver.access_link(search_text="Students")

    def login_email(self):
        self.start_driver()
        self.get("http://outlook.com/hawkmail.hccfl.edu")
        # WebDriverWait(self.driver, 10).until(EC.presence_of_element_located(By.ID, 'ctl00_ContentPlaceHolder1_UsernameTextBox'))
        self.find_box_and_fill(search_text="ctl00_ContentPlaceHolder1_UsernameTextBox", value="cchilders@hawkmail.hccfl.edu")
        self.find_box_and_fill(search_text="ctl00_ContentPlaceHolder1_PasswordTextBox", value="i_love_honey_booboo")
        time.sleep(2)
        self.submit_form("ctl00_ContentPlaceHolder1_SubmitButton")

    def login_myhcc(self):
        driver = FirefoxDriver()
        driver.get("https://hcc.instructure.com")
        time.sleep(5)
        find_box_and_fill('ctl00_ContentPlaceHolder1_UsernameTextBox', 'cchilders@hawkmail.hccfl.edu')
        driver.find_box_and_fill('ctl00_ContentPlawebadvisor_urlceHolder1_PasswordTextBox', 'if_evolution_was_real_americans_would_stop_worshipping_pres_candidates')
        driver.click_button('ctl00$ContentPlaceHolder1$SubmitButton')

关键是,如果没有装饰器,我预见到每个函数看起来像:

def this_func(self, driver=None):
    if not driver:
        try:
            driver = self.driver
        except:
            raise Exception('There is no driver my good sir')

使用driver=None

    try:
        driver = self.driver
    except:
        raise Exception('There is no driver good sir')

部分重复20次,30次等

1 个答案:

答案 0 :(得分:1)

因为你的装饰器是作为一个类而不是一个函数实现的,所以你的装饰color = params[:color] age = params[:age] ... 函数没有包装在绑定的source_code描述符中,因为这是对函数而不是类。

这意味着当您调用method时,没有传递self.func参数。但是您的self方法需要source_code参数,这会导致错误{{ 1}}

在更新版本的Python 3上,您应该获得self。我不确定他们何时添加了明确的信息。

这些评论为您提供了一些关于不同方法的想法,但这解释了您的错误。