def parse_mandatory_option(self, option_name_2_parser: dict): """ A variant of parse_optional_command ,where the command is mandatory. :raises `SingleInstructionInvalidArgumentException': The command is not found """ def expecting_an_option() -> str: options = option_name_2_parser.keys() options_str = '|'.join(map(option_syntax, options)) return 'Expecting : {}{}\nFound : {}'.format( '' if len(options) <= 1 else 'one of ', options_str, self.remaining_part_of_current_line) if self.token_stream.is_null: raise SingleInstructionInvalidArgumentException( expecting_an_option()) elif self._lookahead_token_has_invalid_syntax(): self.require_head_token_has_valid_syntax(expecting_an_option()) key_and_option_name_list = [ (option_name, option_name) for option_name in option_name_2_parser.keys() ] def key_handler(x): return x actual_option = self.consume_and_handle_first_matching_option( None, key_handler, key_and_option_name_list) if actual_option is None: raise SingleInstructionInvalidArgumentException( expecting_an_option()) else: return option_name_2_parser[actual_option](self)
def _raise_invalid_argument_exception_if_symbol_does_not_have_valid_syntax( symbol_name_token: Token, option_str: str): symbol_name = symbol_name_token.source_string if symbol_name_token.is_quoted: msg = 'Symbol name argument for {} must not be quoted: {}'.format( option_str, symbol_name) raise SingleInstructionInvalidArgumentException(msg) if not symbol_syntax.is_symbol_name(symbol_name_token.source_string): msg = 'Invalid name of {symbol_concept}: {invalid_value}'.format( symbol_concept=SYMBOL_CONCEPT_INFO.name.singular, invalid_value=symbol_name_token.source_string, ) raise SingleInstructionInvalidArgumentException(msg)
def extract_single_eq_argument_string(syntax_element: str, rest_of_line: str) -> str: arguments = rest_of_line.strip().split(maxsplit=1) if not arguments: raise SingleInstructionInvalidArgumentException( _missing(instruction_arguments.ASSIGNMENT_OPERATOR)) if arguments[0] != instruction_arguments.ASSIGNMENT_OPERATOR: raise SingleInstructionInvalidArgumentException( expected_found.unexpected_lines_str( instruction_arguments.ASSIGNMENT_OPERATOR, arguments[0])) if len(arguments) != 2: raise SingleInstructionInvalidArgumentException( _missing(syntax_element)) return arguments[1]
def extract_mandatory_arguments_after_eq(syntax_element: str, rest_of_line: str) -> List[str]: arguments = split_arguments_list_string(rest_of_line) if not arguments: raise SingleInstructionInvalidArgumentException( _missing(instruction_arguments.ASSIGNMENT_OPERATOR)) if arguments[0] != instruction_arguments.ASSIGNMENT_OPERATOR: raise SingleInstructionInvalidArgumentException( expected_found.unexpected_lines_str( instruction_arguments.ASSIGNMENT_OPERATOR, arguments[0])) del arguments[0] if not arguments: raise SingleInstructionInvalidArgumentException( _missing(syntax_element)) return arguments
def ensure_is_not_option_argument(argument: str): """ :raises SingleInstructionInvalidArgumentException: The arguments is an option argument. """ if is_option_argument(argument): raise SingleInstructionInvalidArgumentException( 'An option argument was not expected here: {}'.format(argument))
def parse_primitive(self, primitive_name: str) -> EXPR: symbol_name_of_symbol_reference = symbol_syntax.parse_symbol_reference__from_str(primitive_name) if symbol_name_of_symbol_reference is not None: return self.grammar.mk_reference(symbol_name_of_symbol_reference) if primitive_name in self.grammar.primitives: return self.grammar.primitives[primitive_name].parse_arguments(self.parser) elif not symbol_syntax.is_symbol_name(primitive_name): err_msg = self._err_msg_renderer.unknown_primitive(primitive_name) raise SingleInstructionInvalidArgumentException(err_msg) elif primitive_name in self.grammar.custom_reserved_words: err_msg = self._err_msg_renderer.plain_symbol_name_is_reserved_word(primitive_name) raise SingleInstructionInvalidArgumentException(err_msg) else: return self.grammar.mk_reference(primitive_name)
def consume_mandatory_unquoted_string( self, syntax_element_name: str, must_be_on_current_line: bool, error_message: Optional[ErrorMessageGenerator] = None, ) -> str: """ Consumes the first token that must be an unquoted string. :type must_be_on_current_line: Tells if the string must be found on the current line. :return: The unquoted string :raises :class:`SingleInstructionInvalidArgumentException' The parser is at end of file, or if the must_be_on_current_line is True but the current line is empty, or if the parsed token is not an unquoted string. """ if self.token_stream.is_null: return self.error('Expecting ' + syntax_element_name) if self._lookahead_token_has_invalid_syntax(): return self.error('Invalid syntax of ' + syntax_element_name) if self.is_at_eol and must_be_on_current_line: return self.error('Expecting ' + syntax_element_name) head = self.token_stream.head if head.is_quoted: err_msg = 'Expecting unquoted {}.\nFound: `{}\''.format( syntax_element_name, head.source_string) raise SingleInstructionInvalidArgumentException(err_msg) self.token_stream.consume() return head.string
def _resolve_relativity_option_type(option_argument: str) -> RelOptionType: for option_type in rel_opts.REL_OPTIONS_MAP: option_name = rel_opts.REL_OPTIONS_MAP[option_type]._option_name if option_parsing.matches(option_name, option_argument): return option_type raise SingleInstructionInvalidArgumentException( 'Invalid option: {}'.format(option_argument))
def parse_token_or_none_on_current_line(source: ParseSource, argument_description: str = 'argument' ) -> Token: """ Parses a single, optional token from remaining part of current line. Tokens must be separated by space. :param source: Must have a current line. Initial space is consumed. Text for token is consumed. :raise SingleInstructionInvalidArgumentException: The token has invalid syntax """ source.consume_initial_space_on_current_line() if source.is_at_eol: return None part_of_current_line = source.remaining_part_of_current_line source_io = io.StringIO(part_of_current_line) lexer = shlex.shlex(source_io, posix=True) lexer.whitespace_split = True token_type = _derive_token_type(lexer, source.remaining_part_of_current_line[0]) try: token_string = lexer.get_token() except ValueError as ex: msg = 'Invalid {}: {}'.format(argument_description, str(ex)) raise SingleInstructionInvalidArgumentException(msg) source_string = _get_source_string_and_consume_token_characters( source, source_io) return Token(token_type, token_string, source_string)
def _raise_invalid_option(actual: str, options: RelOptionsConfiguration): lines = [ 'Illegal relativity option : {}'.format(actual), 'Legal relativity options :' ] lines.extend(_valid_options_info_lines(options)) msg = '\n'.join(lines) raise SingleInstructionInvalidArgumentException(msg)
def parse_fragments_from_tokens__w_is_plain( tokens: TokenStream, conf: Configuration = DEFAULT_CONFIGURATION) -> Tuple[bool, List[symbol_syntax.Fragment]]: """ Consumes a single token. :raises SingleInstructionInvalidArgumentException: Missing argument """ if tokens.is_null: raise SingleInstructionInvalidArgumentException('Expecting {} argument'.format(conf.argument_name)) string_token = tokens.consume() if string_token.is_plain and string_token.source_string in reserved_words.RESERVED_TOKENS: raise SingleInstructionInvalidArgumentException( 'Illegal {}: {}'.format(conf.argument_name, string_token.source_string), ) return string_token.is_plain, parse_fragments_from_token(string_token)
def parse_from_token_parser(self, parser: TokenParser) -> int: parser.require_has_valid_head_token('INTEGER') int_token = parser.consume_mandatory_token('err msg format string') try: return int(int_token.string) except ValueError: raise SingleInstructionInvalidArgumentException('Not an int: ' + int_token.string)
def _parse_reference_arguments(rest_of_line: str) -> List[SymbolReference]: parts = rest_of_line.split() if len(parts) != 2: raise SingleInstructionInvalidArgumentException( 'Usage TYPE NAME. Found: ' + rest_of_line) type_ident = parts[0] name = parts[1] try: reference = SymbolReference( name, ValueTypeRestriction.of_single( TYPE_IDENT_2_VALUE_TYPE[type_ident])) return [reference] except KeyError: raise SingleInstructionInvalidArgumentException('Not a symbol type: ' + type_ident)
def _parse(self, rest_of_line: str) -> ConfigurationSectionInstruction: py_source_file_name = rest_of_line.strip() if not py_source_file_name or py_source_file_name.isspace(): raise SingleInstructionInvalidArgumentException( 'Missing python source file argument') return Instruction(py_source_file_name)
def split_arguments_list_string(arguments: str) -> List[str]: """ :raises SingleInstructionInvalidArgumentException: The arguments string cannot be parsed. """ try: return shlex.split(arguments) except ValueError as ex: raise SingleInstructionInvalidArgumentException( 'Invalid quoting of arguments: ' + str(ex))
def parse(self, fs_location_info: FileSystemLocationInfo, source: ParseSource) -> ConfigurationPhaseInstruction: rest_of_line = source.remaining_part_of_current_line source.consume_current_line() argument = extract_single_eq_argument_string(_DIR_ARG.name, rest_of_line) path_arguments = split_arguments_list_string(argument) if len(path_arguments) > 1: raise SingleInstructionInvalidArgumentException('Too many arguments: ' + argument) try: path_argument = pathlib.Path(pathlib.PurePosixPath(path_arguments[0])) except ValueError as ex: raise SingleInstructionInvalidArgumentException('Invalid path syntax:\n' + str(ex)) return _Instruction(self.dir_to_set, fs_location_info.current_source_file.abs_path_of_dir_containing_last_file_base_name, path_argument)
def _symbol_string(self, parser: TokenParser) -> str: symbol_string = parser.consume_mandatory_unquoted_string( instruction_arguments.SYMBOL_SYNTAX_ELEMENT_NAME, True) if not symbol_syntax.is_symbol_name(symbol_string): raise SingleInstructionInvalidArgumentException( 'Invalid syntax of ' + instruction_arguments.SYMBOL_SYNTAX_ELEMENT_NAME + ': ' + symbol_string) return symbol_string
def consume_mandatory_keyword( self, keyword: str, must_be_on_current_line: bool, ): actual_string = self.consume_mandatory_unquoted_string( 'keyword ' + keyword, must_be_on_current_line) if actual_string != keyword: raise SingleInstructionInvalidArgumentException( expected_found.unexpected_lines_str(keyword, actual_string))
def _with_non_empty_token_stream( self, tokens: TokenStream) -> Either[SymbolName, PathSdv]: initial_argument_string = tokens.remaining_part_of_current_line relativity_info = parse_explicit_relativity_info( self.conf.rel_opt_conf.options, self.conf.source_file_location, tokens) if not self.conf.rel_opt_conf.path_suffix_is_required and tokens.remaining_part_of_current_line_is_empty: if relativity_info is None: return self._result_from_no_arguments() else: path_part_sdv2_path_sdv = self._path_constructor( relativity_info) return Either.of_right( path_part_sdv2_path_sdv(path_part_sdvs.empty())) if tokens.look_ahead_state is LookAheadState.SYNTAX_ERROR: raise SingleInstructionInvalidArgumentException( std_error_message_text_for_token_syntax_error( tokens.head_syntax_error_description)) elif tokens.look_ahead_state is LookAheadState.NULL: raise SingleInstructionInvalidArgumentException( 'Missing {}: {}'.format( self.conf.rel_opt_conf.argument_syntax_name, initial_argument_string)) head_token = tokens.head if reserved_tokens.IS_RESERVED_WORD.matches(head_token): raise SingleInstructionInvalidArgumentException( 'Illegal file name: {}'.format(head_token.string)) elif head_token.type is TokenType.PLAIN: ensure_is_not_option_argument(head_token.source_string) tokens.consume() if relativity_info is None: return self._without_explicit_relativity(head_token) else: path_part_2_path_sdv = self._path_constructor(relativity_info) return Either.of_right( self._with_explicit_relativity(head_token, path_part_2_path_sdv))
def new_token_stream(source: str) -> TokenStream: """ Constructs a :class:`TokenStream` :rtype: :class:`TokenStream` :raises :class:`SingleInstructionInvalidArgumentException` Invalid syntax """ try: return TokenStream(source) except TokenSyntaxError as ex: raise SingleInstructionInvalidArgumentException( std_error_message_text_for_token_syntax_error_from_exception(ex))
def _parse_from_tokens(self, token_parser: TokenParser) -> InstructionEmbryo[None]: try: phases = self._parse_phases(token_parser) modifier = self._parse_modifier(token_parser) token_parser.report_superfluous_arguments_if_not_at_eol() return _impl.TheInstructionEmbryo(phases, modifier) except TokenSyntaxError as ex: raise SingleInstructionInvalidArgumentException( std_error_message_text_for_token_syntax_error_from_exception(ex))
def consume_mandatory_keyword__part_of_syntax_element( self, keyword: str, must_be_on_current_line: bool, syntax_element_name: str, ): actual_string = self.consume_mandatory_unquoted_string( syntax_element_name, must_be_on_current_line) if actual_string != keyword: raise SingleInstructionInvalidArgumentException( expected_found.unexpected_lines_str__part_of_syntax_element( syntax_element_name, keyword, actual_string))
def _parse(self, rest_of_line: str) -> ConfigurationSectionInstruction: arguments = shlex.split(rest_of_line) if len(arguments) != 2: raise SingleInstructionInvalidArgumentException( 'Invalid syntax: expected: FROM TO') def set_preprocessor(conf: ConfigurationSectionEnvironment): preproc = SearchReplacePreprocessor(arguments[0], arguments[1]) conf.preprocessor = preproc return configuration_section_instruction_that(set_preprocessor)
def _parse(self, rest_of_line: str) -> ConfigurationPhaseInstruction: status_element_arg = extract_single_eq_argument_string( _ARG_NAME, rest_of_line) argument = status_element_arg.upper() try: target = NAME_2_STATUS[argument] except KeyError: raise SingleInstructionInvalidArgumentException( 'Invalid {status}: `{actual}`'.format( status=conf_params.TEST_CASE_STATUS_CONF_PARAM_INFO. configuration_parameter_name, actual=status_element_arg)) return _Instruction(target)
def _parse_from_tokens( self, token_parser: TokenParser) -> InstructionEmbryo[None]: try: token_parser.consume_mandatory_keyword(defs.ASSIGNMENT_IDENTIFIER, False) value = self._parse_value(token_parser) token_parser.report_superfluous_arguments_if_not_at_eol() return _impl.TheInstructionEmbryo(value) except TokenSyntaxError as ex: raise SingleInstructionInvalidArgumentException( std_error_message_text_for_token_syntax_error_from_exception( ex))
def _with_optional_suffix( self, tokens: TokenStream) -> Either[SymbolName, PathSdv]: """ :param tokens: Argument list :raises SingleInstructionInvalidArgumentException: Invalid arguments """ if tokens.look_ahead_state is LookAheadState.SYNTAX_ERROR: raise SingleInstructionInvalidArgumentException( std_error_message_text_for_token_syntax_error( tokens.head_syntax_error_description)) if tokens.is_null or tokens.remaining_part_of_current_line_is_empty: return self._result_from_no_arguments() return self._with_non_empty_token_stream(tokens)
def parse_mb_sym_ref(self, tokens: TokenStream) -> Either[SymbolName, PathSdv]: """ :param tokens: Argument list :raises SingleInstructionInvalidArgumentException: Invalid arguments """ try: if self.conf.rel_opt_conf.path_suffix_is_required: return self._with_required_suffix(tokens) else: return self._with_optional_suffix(tokens) except TokenSyntaxError as ex: raise SingleInstructionInvalidArgumentException( std_error_message_text_for_token_syntax_error_from_exception( ex))
def parse_plain_token_on_current_line(source: ParseSource, argument_description: str = 'argument' ) -> Token: """ Parses a single, mandatory plain (unquoted) token from remaining part of current line. Tokens must be separated by space. :param source: Must have a current line. Initial space is consumed. Text for token is consumed. :raise SingleInstructionInvalidArgumentException: There is no token :raise SingleInstructionInvalidArgumentException: The token has invalid syntax """ token = parse_token_on_current_line(source, argument_description) if token.type is TokenType.QUOTED: raise SingleInstructionInvalidArgumentException( 'Argument must not be quoted: ' + token.source_string) return token
def parse_token_on_current_line(source: ParseSource, argument_description: str = 'argument' ) -> Token: """ Parses a single, mandatory token from remaining part of current line. Tokens must be separated by space. :param source: Must have a current line. Initial space is consumed. Text for token is consumed. :raise SingleInstructionInvalidArgumentException: There is no token :raise SingleInstructionInvalidArgumentException: The token has invalid syntax """ token = parse_token_or_none_on_current_line(source, argument_description) if token is None: raise SingleInstructionInvalidArgumentException('Missing ' + argument_description) return token
def _try_parse_rel_symbol_option( options: RelOptionsConfiguration, source: TokenStream) -> Optional[SymbolReference]: option_str = source.head.string if not option_parsing.matches(REL_SYMBOL_OPTION_NAME, option_str): return None source.consume() if source.is_null: msg = 'Missing symbol name argument for {} option'.format(option_str) raise SingleInstructionInvalidArgumentException(msg) _raise_invalid_argument_exception_if_symbol_does_not_have_valid_syntax( source.head, option_str) symbol_name = source.consume().string return SymbolReference( symbol_name, reference_restrictions_for_path_symbol( options.accepted_relativity_variants))