from munch import munchify class Locator: locator_kinds = {"id", "xpath"} _context = None def __init__(self, *args, **kwargs): self.valid_parameters = [f"find_by__{kind}" for kind in self.locator_kinds] self._locators = {} for param, value in kwargs.items(): if param not in self.valid_parameters: raise TypeError(f"You need to pass a valid locator: {self.locator_kinds}") else: identifier = param[9:] if identifier not in self._locators: self._locators[identifier] = value # parameters = [] # if "find_by" not in kwargs: # raise TypeError("You need to specify find_by argument") @property def context(self): if not hasattr(self, "_context"): raise TypeError("Context not settled") return getattr(self, "_context") @context.setter def context(self, value): print("setting context") setattr(self, "_context", value) setattr(self, "_munch_context", munchify(value)) def _get_element(self): for loc, value in self._locators.items(): if value in self._munch_context.driver: return getattr(self._munch_context.driver, value) raise IndexError("Not found element in driver") def __getattr__(self, item): el_instance = self._get_element() attr = getattr(el_instance, item) if not callable(attr): return attr def wrapper(*args, **kwargs): return attr(*args, **kwargs) return wrapper class Screen(object): def __new__(cls, *args, **kwargs): ctx_in_args = len(args) > 0 if not ctx_in_args: raise TypeError("No context provided") context = args[0] instance = object.__new__(cls) instance.__init__(*args, **kwargs) elements = [getattr(instance, el) for el in dir(instance) if isinstance(getattr(instance, el), Locator)] for el in elements: setattr(el, "context", context) return instance class LoginScreen(Screen): understand_button = Locator(find_by__id="btn") terms_text = Locator(find_by__id="txt") def click_to_understand(self): self.understand_button.click() def terms_is_right(self): print(self.terms_text.value == "Test") if __name__ == '__main__': class B: content = "Clicked" def click(self): print(self.content) class C: @property def value(self): return "Test" context = {"driver": {"btn": B(), "txt": C()}} s = LoginScreen(context) s.click_to_understand() s.terms_is_right() B.content = "Changed" s.click_to_understand()