def navigate(self, name: str, selector: Optional[str]) -> "CommandClient": """Resolve the given object in the command graph Parameters ---------- name : str The name of the command graph object to resolve. selector : Optional[str] If given, the selector to use to select the next object, and if None, then selects the default object. Returns ------- CommandClient The client with the given command graph object resolved. """ if not isinstance(self._current_node, CommandGraphNode): raise SelectError("Invalid navigation", "", self._current_node.selectors) if name not in self.children: raise SelectError("Not valid child", name, self._current_node.selectors) if selector is not None: if self._command.has_item(self._current_node, name, selector): raise SelectError("Item not available in object", name, self._current_node.selectors) next_node = self._current_node.navigate(name, selector) return self.__class__(self._command, current_node=next_node)
def navigate(self, name: str, selector: str | None) -> CommandClient: """Resolve the given object in the command graph Parameters ---------- name: str The name of the command graph object to resolve. selector: str | None If given, the selector to use to select the next object, and if None, then selects the default object. Returns ------- CommandClient The client with the given command graph object resolved. """ if name not in self.children: raise SelectError("Not valid child", name, self._current_node.selectors) normalized_selector = _normalize_item( name, selector) if selector is not None else None if normalized_selector is not None: if not self._command.has_item(self._current_node, name, normalized_selector): raise SelectError("Item not available in object", name, self._current_node.selectors) next_node = self._current_node.navigate(name, normalized_selector) return self.__class__(self._command, current_node=next_node)
def __getattr__(self, name: str) -> "InteractiveCommandClient": """Get the child element of the currently selected object Resolve the element specified by the given name, either the child object, or the command on the current object. Parameters ---------- name : str The name of the element to resolve Return ------ InteractiveCommandClient The client navigated to the specified name. Will respresent either a command graph node (if the name is a valid child) or a command graph call (if the name is a valid command). """ if isinstance(self._current_node, CommandGraphCall): raise SelectError("Cannot select children of call", name, self._current_node.selectors) # we do not know if the name is a command to be executed, or an object # to navigate to if name not in self._current_node.children: # we are going to resolve a command, check that the command is valid if not self._command.has_command(self._current_node, name): raise SelectError("Not valid child or command", name, self._current_node.selectors) call_object = self._current_node.call(name) return self.__class__(self._command, current_node=call_object) next_node = self._current_node.navigate(name, None) return self.__class__(self._command, current_node=next_node)
def __getattr__(self, name: str) -> InteractiveCommandClient: """Get the child element of the currently selected object Resolve the element specified by the given name, either the child object, or the command on the current object. Parameters ---------- name: str The name of the element to resolve Return ------ InteractiveCommandClient The client navigated to the specified name. Will respresent either a command graph node (if the name is a valid child) or a command graph call (if the name is a valid command). """ # Python's help() command will try to look up __name__ and __origin__ so we # need to handle these explicitly otherwise they'll result in a SelectError # which help() does not expect. if name in ["__name__", "__origin__"]: raise AttributeError if isinstance(self._current_node, CommandGraphCall): raise SelectError( "Cannot select children of call", name, self._current_node.selectors ) # we do not know if the name is a command to be executed, or an object # to navigate to if name not in self._current_node.children: # we are going to resolve a command, check that the command is valid if not self._command.has_command(self._current_node, name): raise SelectError( "Not valid child or command", name, self._current_node.selectors ) call_object = self._current_node.call(name) return self.__class__(self._command, current_node=call_object) next_node = self._current_node.navigate(name, None) return self.__class__(self._command, current_node=next_node)
def __getitem__(self, name: str | int) -> InteractiveCommandClient: """Get the selected element of the currently selected object From the current command graph object, select the instance with the given name. Parameters ---------- name: str The name, or index if it's of int type, of the item to resolve Return ------ InteractiveCommandClient The current client, navigated to the specified command graph object. """ if isinstance(self._current_node, CommandGraphRoot): raise KeyError("Root node has no available items", name, self._current_node.selectors) if not isinstance(self._current_node, CommandGraphObject): raise SelectError( "Unable to make selection on current node", str(name), self._current_node.selectors, ) if self._current_node.selector is not None: raise SelectError("Selection already made", str(name), self._current_node.selectors) # check the selection is valid in the server-side qtile manager if not self._command.has_item(self._current_node.parent, self._current_node.object_type, name): raise SelectError("Item not available in object", str(name), self._current_node.selectors) next_node = self._current_node.parent.navigate( self._current_node.object_type, name) return self.__class__(self._command, current_node=next_node)
def _normalize_item(object_type: str | None, item: str) -> str | int: if object_type in ["group", "widget", "bar"]: return str(item) elif object_type in ["layout", "window", "screen"]: try: return int(item) except ValueError: # A value error could arise because the next selector has been passed raise SelectError( f"Unexpected index {item}. Is this an object_type?", str(object_type), [(str(object_type), str(item))], ) else: return item
def call(self, name: str) -> "CommandClient": """Resolve the call into the command graph Parameters ---------- name : str The name of the command to resolve in the command graph. Returns ------- CommandClient The client with the command resolved. """ if not isinstance(self._current_node, CommandGraphNode): raise SelectError("Invalid navigation", "", self._current_node.selectors) command_call = self._current_node.call("commands") commands = self._command.execute(command_call, (), {}) if name not in commands: raise SelectError("Not valid child or command", name, self._current_node.selectors) next_node = self._current_node.call(name) return self.__class__(self._command, current_node=next_node)
def call(self, name: str, *args, **kwargs) -> Any: """Resolve and invoke the call into the command graph Parameters ---------- name: str The name of the command to resolve in the command graph. args: The arguments to pass into the call invocation. kwargs: The keyword arguments to pass into the call invocation. Returns ------- The output returned from the function call. """ if name not in self.commands: raise SelectError("Not valid child or command", name, self._current_node.selectors) call = self._current_node.call(name) return self._command.execute(call, args, kwargs)
def __call__(self, *args, **kwargs) -> Any: """When the client has navigated to a command, execute it""" if not isinstance(self._current_node, CommandGraphCall): raise SelectError("Invalid call", "", self._current_node.selectors) return self._command.execute(self._current_node, args, kwargs)
def parent(self) -> CommandClient: """Get the parent of the current client""" if self._current_node.parent is None: raise SelectError("", "", self._current_node.selectors) return self.__class__(self._command, current_node=self._current_node.parent)
def children(self) -> List[str]: """Get the children of the current location in the command graph""" if isinstance(self._current_node, CommandGraphCall): raise SelectError("No children of command graph call", "", self._current_node.selectors) return self._current_node.children