1from typing import Any 2from typing import Dict 3from typing import List 4from typing import Optional 5from typing import Union 6 7from ..exceptions import NoSuchArgumentException 8from ..exceptions import NoSuchOptionException 9 10from .argument import Argument 11from .option import Option 12from .command_name import CommandName 13from .command_option import CommandOption 14 15 16class ArgsFormat(object): 17 """ 18 The format used to parse a RawArgs instance. 19 """ 20 21 def __init__( 22 self, elements=None, base_format=None 23 ): # type: (Optional[Union[List[Any], ArgsFormatBuilder]], Optional[ArgsFormat]) 24 from .args_format_builder import ArgsFormatBuilder 25 26 if elements is None: 27 elements = [] 28 29 if isinstance(elements, ArgsFormatBuilder): 30 builder = elements 31 else: 32 builder = self._create_builder_for_elements(elements) 33 34 if base_format is None: 35 base_format = builder.base_format 36 37 self._base_format = base_format 38 self._command_names = builder.get_command_names(False) 39 self._command_options = {} 40 self._command_options_by_short_name = {} 41 self._arguments = builder.get_arguments(False) 42 self._options = builder.get_options(False) 43 self._options_by_short_name = {} 44 self._has_multi_valued_arg = builder.has_multi_valued_argument(False) 45 self._hash_optional_arg = builder.has_optional_argument(False) 46 47 for option in self._options.values(): 48 if option.short_name: 49 self._options_by_short_name[option.short_name] = option 50 51 for command_option in builder.get_command_options(): 52 self._command_options[command_option.long_name] = command_option 53 54 if command_option.short_name: 55 self._command_options_by_short_name[ 56 command_option.short_name 57 ] = command_option 58 59 for long_alias in command_option.long_aliases: 60 self._command_options[long_alias] = command_option 61 62 for short_alias in command_option.short_aliases: 63 self._command_options_by_short_name[short_alias] = command_option 64 65 @property 66 def base_format(self): # type: () -> ArgsFormat 67 return self._base_format 68 69 def has_command_names(self, include_base=True): # type: (bool) -> bool 70 if self._command_names: 71 return True 72 73 if include_base and self._base_format: 74 return self._base_format.has_command_names() 75 76 return False 77 78 def get_command_names(self, include_base=True): # type: (bool) -> List[CommandName] 79 command_names = self._command_names 80 81 if include_base and self._base_format: 82 command_names = self._base_format.get_command_names() + command_names 83 84 return command_names 85 86 def has_command_option(self, name, include_base=True): # type: (str, bool) -> bool 87 if name in self._command_options or name in self._command_options_by_short_name: 88 return True 89 90 if include_base and self._base_format: 91 return self._base_format.has_command_option(name) 92 93 return False 94 95 def has_command_options(self, include_base=True): # type: (bool) -> bool 96 if self._command_options: 97 return True 98 99 if include_base and self._base_format: 100 return self._base_format.has_command_options() 101 102 return False 103 104 def get_command_option( 105 self, name, include_base=True 106 ): # type: (str, bool) -> CommandOption 107 if name in self._command_options: 108 return self._command_options[name] 109 110 if name in self._command_options_by_short_name: 111 return self._command_options_by_short_name[name] 112 113 if include_base and self._base_format: 114 return self._base_format.get_command_option(name) 115 116 raise NoSuchOptionException(name) 117 118 def get_command_options( 119 self, include_base=True 120 ): # type: (bool) -> List[CommandOption] 121 command_options = list(self._command_options.values()) 122 123 if include_base and self._base_format: 124 command_options += self._base_format.get_command_options() 125 126 return command_options 127 128 def has_argument( 129 self, name, include_base=True 130 ): # type: (Union[str, int], bool) -> bool 131 arguments = self.get_arguments(include_base) 132 133 if isinstance(name, int): 134 return name < len(arguments) 135 136 return name in arguments 137 138 def has_multi_valued_argument(self, include_base=True): # type: (bool) -> bool 139 if self._has_multi_valued_arg: 140 return True 141 142 if include_base and self._base_format: 143 return self._base_format.has_multi_valued_argument() 144 145 return False 146 147 def has_optional_argument(self, include_base=True): # type: (bool) -> bool 148 if self._hash_optional_arg: 149 return True 150 151 if include_base and self._base_format: 152 return self._base_format.has_optional_argument() 153 154 return False 155 156 def has_required_argument(self, include_base=True): # type: (bool) -> bool 157 if not self._hash_optional_arg and self._arguments: 158 return True 159 160 if include_base and self._base_format: 161 return self._base_format.has_required_argument() 162 163 return False 164 165 def has_arguments(self, include_base=True): # type: (bool) -> bool 166 if self._arguments: 167 return True 168 169 if include_base and self._base_format: 170 return self._base_format.has_arguments() 171 172 return False 173 174 def get_argument( 175 self, name, include_base=True 176 ): # type: (Union[str, int], bool) -> Argument 177 if isinstance(name, int): 178 arguments = list(self.get_arguments(include_base).values()) 179 180 if name >= len(arguments): 181 raise NoSuchArgumentException(name) 182 else: 183 arguments = self.get_arguments(include_base) 184 185 if name not in arguments: 186 raise NoSuchArgumentException(name) 187 188 return arguments[name] 189 190 def get_arguments(self, include_base=True): # type: (bool) -> Dict[str, Argument] 191 arguments = self._arguments.copy() 192 193 if include_base and self._base_format: 194 base_arguments = self._base_format.get_arguments() 195 base_arguments.update(arguments) 196 arguments = base_arguments 197 198 return arguments 199 200 def has_option(self, name, include_base=True): # type: (str, bool) -> bool 201 if name in self._options or name in self._options_by_short_name: 202 return True 203 204 if include_base and self._base_format: 205 return self._base_format.has_option(name) 206 207 return False 208 209 def has_options(self, include_base=True): # type: (bool) -> bool 210 if self._options: 211 return True 212 213 if include_base and self._base_format: 214 return self._base_format.has_options() 215 216 return False 217 218 def get_option(self, name, include_base=True): # type: (str, bool) -> Option 219 if name in self._options: 220 return self._options[name] 221 222 if name in self._options_by_short_name: 223 return self._options_by_short_name[name] 224 225 if include_base and self._base_format: 226 return self._base_format.get_option(name) 227 228 raise NoSuchOptionException(name) 229 230 def get_options(self, include_base=True): # type: (bool) -> Dict[str, Option] 231 options = self._options.copy() 232 233 if include_base and self._base_format: 234 options.update(self._base_format.get_options()) 235 236 return options 237 238 def _create_builder_for_elements( 239 self, elements, base_format=None 240 ): # type: (List[Any], Optional[ArgsFormat]) -> ArgsFormatBuilder 241 from .args_format_builder import ArgsFormatBuilder 242 243 builder = ArgsFormatBuilder(base_format) 244 245 for element in elements: 246 if isinstance(element, CommandName): 247 builder.add_command_name(element) 248 elif isinstance(element, CommandOption): 249 builder.add_command_option(element) 250 elif isinstance(element, Option): 251 builder.add_option(element) 252 elif isinstance(element, Argument): 253 builder.add_argument(element) 254 255 return builder 256