pipewire_python._utils
Here we store internal functions, don't expect to see something here in documentation html version.
1""" 2Here we store internal functions, don't expect 3to see something here in documentation html version. 4""" 5import asyncio 6import re 7import subprocess 8from typing import Dict, List 9 10# Loading constants Constants.py 11from ._constants import MESSAGES_ERROR 12 13 14def _print_std( 15 stdout: bytes, 16 stderr: bytes, 17 # Debug 18 verbose: bool = False, 19): 20 """ 21 Print terminal output if are different to None and verbose activated 22 """ 23 24 if stdout is not None and verbose: 25 print(f"[_print_std][stdout][type={type(stdout)}]\n{stdout.decode()}") 26 if stderr is not None and verbose: 27 print(f"[_print_std][stderr][type={type(stderr)}]\n{stderr.decode()}") 28 29 30def _get_dict_from_stdout( 31 stdout: str, 32 # Debug 33 verbose: bool = False, 34): 35 """ 36 Converts shell output (str) to dictionary looking for 37 "default" and "--" values 38 """ 39 40 rows = stdout.split("\n") 41 config_dict = {} 42 for row in rows: 43 if "default" in row: 44 key = "--" + row.split("--")[1].split(" ")[0] 45 value = row.split("default ")[1].replace(")", "") 46 config_dict[key] = value 47 if verbose: 48 print(config_dict) 49 return config_dict 50 51 52def _update_dict_by_dict( 53 main_dict: Dict, 54 secondary_dict: Dict, 55): 56 """ 57 Update values of one dictionary with values of another dictionary 58 based on keys 59 """ 60 return main_dict.update(([(key, secondary_dict[key]) for key in secondary_dict.keys()])) 61 62 63def _drop_keys_with_none_values(main_dict: dict): 64 """ 65 Drop keys with None values to parse safe dictionary config 66 """ 67 return {k: v for k, v in main_dict.items() if v is not None} 68 69 70def _generate_command_by_dict( 71 mydict: Dict, 72 # Debug 73 verbose: bool = False, 74): 75 """ 76 Generate an array based on dictionary with keys and values 77 """ 78 array_command = [] 79 # append to a list 80 for key, value in mydict.items(): 81 array_command.extend([key, value]) 82 if verbose: 83 print(array_command) 84 # return values 85 return array_command 86 87 88def _execute_shell_command( 89 command: List[str], 90 timeout: int = -1, # *default= no limit 91 # Debug 92 verbose: bool = False, 93): 94 """ 95 Execute command on terminal via subprocess 96 97 Args: 98 - command (str): command line to execute. Example: 'ls -l' 99 - timeout (int): (seconds) time to end the terminal process 100 - verbose (bool): print variables for debug purposes 101 Return: 102 - stdout (str): terminal response to the command 103 - stderr (str): terminal response to the command 104 """ 105 # Create subprocess 106 # NO-RESOURCE-ALLOCATING 107 # terminal_subprocess = subprocess.Popen( 108 # command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT # Example ['ls ','l'] 109 # ) 110 111 with subprocess.Popen( 112 command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT # Example ['ls ','l'] 113 ) as terminal_subprocess: 114 # Execute command depending or not in timeout 115 try: 116 if timeout == -1: 117 stdout, stderr = terminal_subprocess.communicate() 118 else: 119 stdout, stderr = terminal_subprocess.communicate(timeout=timeout) 120 except subprocess.TimeoutExpired: # When script finish in time 121 terminal_subprocess.kill() 122 stdout, stderr = terminal_subprocess.communicate() 123 124 # Print terminal output 125 _print_std(stdout, stderr, verbose=verbose) 126 127 # Return terminal output 128 return stdout, stderr 129 130 131async def _execute_shell_command_async( 132 command, 133 timeout: int = -1, 134 # Debug 135 verbose: bool = False, 136): 137 """[ASYNC] Function that execute terminal commands in asyncio way 138 139 Args: 140 - command (str): command line to execute. Example: 'ls -l' 141 Return: 142 - stdout (str): terminal response to the command. 143 - stderr (str): terminal response to the command. 144 """ 145 if timeout == -1: 146 # No timeout 147 terminal_process_async = await asyncio.create_subprocess_shell( 148 command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE 149 ) 150 stdout, stderr = await terminal_process_async.communicate() 151 print( 152 f"[_execute_shell_command_async]\ 153 [{command!r} exited with\ 154 {terminal_process_async.returncode}]" 155 ) 156 _print_std(stdout, stderr, verbose=verbose) 157 158 else: 159 raise NotImplementedError(MESSAGES_ERROR["NotImplementedError"]) 160 161 return stdout, stderr 162 163 164def _generate_dict_list_targets( 165 longstring: str, # string output of shell 166 # Debug 167 verbose: bool = False, 168): 169 """ 170 Function that transform long string of list targets 171 to a `dict` 172 """ 173 174 regex_id = r"(\d.*):" 175 regex_desc = r'description="([^"]*)"' 176 regex_prio = r"prio=(-?\d.*)" 177 regex_default_node = r"[*]\t(\d\d)" 178 regex_alsa_node = r"(alsa_[a-zA-Z].*)" 179 180 results_regex_id = re.findall(regex_id, longstring) 181 results_regex_desc = re.findall(regex_desc, longstring) 182 results_regex_prio = re.findall(regex_prio, longstring) 183 results_regex_default_node = re.findall(regex_default_node, longstring) 184 results_regex_alsa_mode = re.findall(regex_alsa_node, longstring) 185 186 mydict = {} 187 for idx, _ in enumerate(results_regex_id): 188 mydict[results_regex_id[idx]] = { 189 "description": results_regex_desc[idx], 190 "prior": results_regex_prio[idx], 191 } 192 mydict["_list_nodes"] = results_regex_id 193 mydict["_node_default"] = results_regex_default_node 194 mydict["_alsa_node"] = results_regex_alsa_mode 195 196 if verbose: 197 print(mydict) 198 199 return mydict 200 201 202def _generate_dict_interfaces( 203 longstring: str, # string output of shell 204 # Debug 205 verbose: bool = False, 206): 207 """ 208 Function that transform long string of list interfaces 209 to a `dict` 210 """ 211 212 mydict = {} 213 text_in_lines = longstring.split("\n") 214 first_level = "X" 215 216 for line in text_in_lines: 217 try: 218 is_interface = True 219 if "id: " in line: 220 # when interface starts 221 regex_id = r"\tid: ([0-9]*)" 222 results_regex_id = re.findall(regex_id, line) 223 is_interface = False 224 225 if is_interface: 226 if "*" in line[:1]: 227 # delete * on each line at the beginning 228 line = line[1:] 229 if "\t\t" in line: 230 # third level data 231 data = line.replace("\t\t", "") 232 data = data.split(" = ") 233 third_level = str(data[0]) 234 data_to_place = " ".join(data[1:]).replace('"', "") 235 236 if "properties" not in mydict[first_level]: 237 mydict[first_level]["properties"] = {} 238 if third_level not in mydict[first_level]["properties"]: 239 mydict[first_level]["properties"][third_level] = {} 240 mydict[first_level]["properties"][third_level] = data_to_place 241 242 elif "\t " in line: 243 # second level data: params 244 245 data = line.replace("\t ", "").split(" ") 246 third_level = str(data[0]) 247 if type(mydict[first_level]["params"]) != dict: 248 mydict[first_level]["params"] = {} 249 mydict[first_level]["params"][third_level] = { 250 "spa": data[1], 251 "permissions": data[2], 252 } 253 254 elif "\t" in line: 255 # first level data 256 data = line.replace("\t", "") 257 data = data.split(": ") 258 first_level = str(results_regex_id[0]) 259 second_level = str(data[0]) 260 data_to_place = " ".join(data[1:]).replace('"', "") 261 262 # to_dict 263 if first_level not in mydict: 264 mydict[str(first_level)] = {} 265 266 mydict[first_level][second_level] = data_to_place 267 except Exception as e: 268 print(e) 269 270 if verbose: 271 print(mydict) 272 273 return mydict 274 275 276def _filter_by_type( 277 dict_interfaces: dict, # interfaecs dict 278 type_interfaces: str, # string with type 279 # Debug 280 verbose: bool = False, 281): 282 """ 283 Function that filters a `dict` by type of interface 284 """ 285 286 dict_filtered = {} 287 for key in dict_interfaces: 288 # Filter 289 if type_interfaces in dict_interfaces[key]["type"]: 290 dict_filtered[key] = dict_interfaces[key] 291 292 if verbose: 293 print(dict_filtered) 294 295 return dict_filtered