Python 3.8 Walrus Operator with not and assigning mutliple variables

2.5k views Asked by At

I am working on a selenium wrapper. I want to check if an element on the webpage is visible . The function gets the input variable selector which follows the pattern "selector=value" so e.g "id=content" but could also be this "link_text=Hello World". The search function splits that string into its two parts for searching the actual element and returns it for use in the errorhandling. The excpetion message should state both the selector and the value:

class KeywordFailed(Exception):
    
    def __init__(self, message):
        self.message = message
        super().__init__(self.message)

class ElementFoundButNotVisible(KeywordFailed):
    def __init__(self, element, selector):
        super().__init__("element: \"" + element + "\" with selector: \"" + selector + "\" is not visible")

class DefaultKeywords:

    browser = webdriver.Firefox()

    def selectElement(self, selector):
        selectorValue = selector.split("=")[1]
        selector = selector.split("=")[0]
        try:
            if selector == "id":
                element = self.browser.find_element_by_id(selectorValue)
            elif selector == "xpath":
                element = self.browser.find_element_by_xpath(selectorValue)
            elif selector == "link_text":
                element = self.browser.find_element_by_link_text(selectorValue)
            elif selector == "partial_link_text":
                element = self.browser.find_element_by_partial_link_text(selectorValue)
            elif selector == "name":
                element = self.browser.find_element_by_name(selectorValue)
            elif selector == "class_name":
                element = self.browser.find_element_by_class_name(selectorValue)
            elif selector == "css_selector":
                element = self.browser.find_element_by_css_selector(selectorValue)
            elif selector == "tag":
                element = self.browser.find_element_by_tag_name(selectorValue)
        except NoSuchElementException:
            raise ElementNotFound(selectorValue, selector)
        else:
            return element, selector

    def findAndCheckIfVisible(self, selector):
        if (value, selector) := not self.selectElement(selector).is_displayed():
            raise ElementFoundButNotVisible(element, selector)
...

When executing though I get the following error:

SyntaxError: cannot use assignment expressions with tuple

I could move the separation process into an function of its own and just call it one in the exception and in the search function but I really don't want to do that as that would mean I am executing the same code twice.

1

There are 1 answers

0
Ajax1234 On BEST ANSWER

You cannot use a form of unpacking with assignment expressions. Instead, consider using the assignment expression to create a name to the returned tuple, and then unpacking from the name from the expression:

def findAndCheckIfVisible(self, selector):
   if not (result:=self.selectElement(selector).is_displayed()):
      raise ElementFoundButNotVisible(element, selector)
   value, selector = result

Also, instead of explicit conditionals for each selector type, consider using getattr:

try:
   element = getattr(self.browser, f'find_element_by_{selector}')(selectorValue)
except NoSuchElementException:
   pass