def __new__(mcs, class_name, bases, attrs): if class_name != 'Table': columns = {} base_table = None for cls_ in bases: if cls_.__name__ == 'Table': base_table = cls_ break if not base_table: raise BaseTableException( f'class<{class_name}> must be inheriting from Table') for name, item in attrs.items(): if not name.startswith('__') and name in base_table.__dict__: raise BaseTableException( f'Attribute with name="{name}" overrides parent Table attribute' ) if item is not None: try: item._set_parent except AttributeError: continue else: columns[name] = item attrs['_columns'] = columns table = type.__new__(mcs, class_name, bases, attrs) return table
def _set_parent(self, table): if not self._attr_name: raise BaseTableException( 'Column object must be attribute of Table obj') existing = getattr(self, 'table', None) if existing is not None and existing is not table: raise BaseTableException( f"Column object '{self._attr_name}' already assigned to Table '{existing}'" ) if self.search_attr_name: table._head_search_attrs.add(self.search_attr_name) self.table = table
def __getitem__(self, item: int) -> WebElementProxy: """ Возвращает ячейку колонки по её номеру (нумерация начинается с 1) Использование: column[<номер_строки_в_колонке>] :param item: :return: """ if not isinstance(item, int) or item < 1: raise BaseTableException('Column item index must be integer >= 1') return self.table._get_column_cell_by_index(self, item)
def __init__(self, search_value: str = None, search_attribute: str = TABLE_ATTRIBUTE, tag_name: str = TABLE_TAG): """ Всегда возвращает первую таблицу, найденную по заданным параметрам :param search_value: значение атрибута для поиска :param search_attribute: дополнительный атрибут, по которому искать таблицу :param tag_name: тэг, в который закллючена таблица """ if self.__class__ == Table: raise BaseTableException( 'You must inherit from Table class. Do not use directly') self._head_search_attrs = set() self._tag_name = tag_name if search_value and not search_attribute: raise BaseTableException( 'search_attribute and search_value must be set together') self.value = self._compile_search_xpath(search_attribute, search_value) self.init_columns()
def get_column_index(self, column: Column) -> int: """ Возвращает индекс колонки по видимому тексту тэга, либо по значению его атрибута. Значение атрибута приоритетно :param column :return: """ if column.search_attr_value: return self.columns_indexes.get(column.search_attr_name, {}).get(column.search_attr_value) col_index = self.columns_indexes.get(self._head_tag_text_key, {}).get(column.visible_name) if not col_index: raise BaseTableException( f'Cannot find index of {column} in {self}') return col_index
def _compile_xpath_by_attribute_name(self, name: str, value: str): if not (value and name): raise BaseTableException( 'attr_name and attr_value must be pass if search_type is attribute_name' ) return f'//{self.head_tag_name}[@{name}="{value}"]'
def __getattr__(self, item): # часть магии происходит здесь, таблица часть вызовов прокидывает в свою родительскую страницу if self.page: return getattr(self.page, item) raise BaseTableException( f'{self.__class__.__name__} not initialized from Page object')