コード例 #1
0
class MultiBoxSelect(Widget):

    TABLE = "//table[@id={}]{}"

    def __init__(self, parent, id, number="", move_into=None, move_from=None,
            available_items="choices_chosen", chosen_items="members_chosen", logger=None):
        Widget.__init__(self, parent, logger=logger)
        self.available_options = Select(self, id=available_items)
        self.chosen_options = Select(self, id=chosen_items)
        self.id = id
        if number:
            self.number = "[{}]".format(number)
        else:
            self.number = number
        if isinstance(move_into, WidgetDescriptor):
            self._move_into = move_into.klass(self, **move_into.kwargs)
        else:
            self._move_into = move_into
        if isinstance(move_from, WidgetDescriptor):
            self._move_from = move_from.klass(self, **move_from.kwargs)
        else:
            self._move_from = move_from

    def __locator__(self):
        return self.TABLE.format(quote(self.id), self.number)

    def _values_to_remove(self, values):
        return list((set(values) ^ self.read()) - set(values))

    def _values_to_add(self, values):
        return list((set(values) ^ self.read()) - self.read())

    @property
    def move_into_button(self):
        """This method is required to avoid 'Element is no longer attached to the DOM'
        Selenium exception.
        """
        if isinstance(self._move_into, Button):
            button = self._move_into
        elif isinstance(self._move_into, basestring):
            button = self.browser.element(self._move_into, self)
        return button

    @property
    def move_from_button(self):
        if isinstance(self._move_from, Button):
            button = self._move_from
        elif isinstance(self._move_from, basestring):
            button = self.browser.element(self._move_from, self)
        return button

    def fill(self, values):
        if set(values) == self.read():
            return False
        else:
            values_to_remove = self._values_to_remove(values)
            values_to_add = self._values_to_add(values)
            if values_to_remove:
                self.chosen_options.fill(values_to_remove)
                self.move_from_button.click()
                self.browser.plugin.ensure_page_safe()
            if values_to_add:
                self.available_options.fill(values_to_add)
                self.move_into_button.click()
                self.browser.plugin.ensure_page_safe()
            return True

    def read(self):
        return {option.text for option in self.chosen_options.all_options}