Ejemplo n.º 1
0
    def execute_command(self, source: InfoCommandSource, command: str):
        first_literal_element = utils.get_element(command)
        plugin_root_nodes = self.root_nodes.get(first_literal_element, [])
        if len(plugin_root_nodes) > 0 and source.is_console:
            # If this is a command, don't send it towards the server if it's from console input
            source.get_info().cancel_send_to_server()

        command_errors = []
        for plugin_root_node in plugin_root_nodes:
            plugin = plugin_root_node.plugin
            node = plugin_root_node.node
            with self.mcdr_server.plugin_manager.with_plugin_context(plugin):
                try:
                    node.execute(source, command)
                except CommandError as e:
                    command_errors.append(e)
                except:
                    self.logger.exception(
                        'Error when executing command "{}" with command source "{}" on {} registered by {}'
                        .format(command, source, node, plugin))
        for error in command_errors:
            if not error.is_handled():
                translation_key = 'command_exception.{}'.format(
                    string_util.hump_to_underline(type(error).__name__))
                try:
                    error.set_translated_message(
                        translation_key, lambda key, args: self.mcdr_server.tr(
                            key, *args, allow_failure=False))
                except KeyError:
                    self.logger.debug(
                        'Fail to translated command error with key {}'.format(
                            translation_key),
                        option=DebugOption.COMMAND)
                source.reply(error.to_mc_color_text())
Ejemplo n.º 2
0
	def _execute(self, source, command: str, remaining: str, context: dict):
		success_read = len(command) - len(remaining)
		try:
			result = self.parse(remaining)
		except CommandSyntaxError as error:
			error.set_parsed_command(command[:success_read])
			error.set_failed_command(command[:success_read + error.char_read])
			self.__raise_error(source, error, context)
		else:
			success_read += result.char_read
			trimmed_remaining = utils.remove_divider_prefix(remaining[result.char_read:])

			if self.__does_store_thing():
				context[self.name] = result.value

			if self.requirement is not None:
				if not self.__smart_callback(self.requirement, source, context):
					getter = self.requirement_failure_message_getter if self.requirement_failure_message_getter is not None else lambda: None
					failure_message = self.__smart_callback(getter, source, context)
					self.__raise_error(source, RequirementNotMet(command[:success_read], command[:success_read], failure_message), context)

			# Parsing finished
			if len(trimmed_remaining) == 0:
				if self.callback is not None:
					self.__smart_callback(self.callback, source, context)
				else:
					self.__raise_error(source, UnknownCommand(command[:success_read], command[:success_read]), context)
			# Un-parsed command string remains
			else:
				# Redirecting
				node = self if self.redirect_node is None else self.redirect_node

				argument_unknown = False
				# No child at all
				if not node.has_children():
					argument_unknown = True
				else:
					# Pass the remaining command string to the children
					try:
						# Check literal children first
						next_literal = utils.get_element(trimmed_remaining)
						for child_literal in node.children_literal.get(next_literal, []):
							try:
								child_literal._execute(source, command, trimmed_remaining, context)
								break
							except LiteralNotMatch:
								# it's ok for a direct literal node to fail
								pass
						else:  # All literal children fails
							for child in node.children:
								child._execute(source, command, trimmed_remaining, context)
								break
							else:  # No argument child
								argument_unknown = True
					except CommandError as error:
						self.__handle_error(source, error, context, self.child_error_handlers)
						raise error from None

				if argument_unknown:
					self.__raise_error(source, UnknownArgument(command[:success_read], command), context)
Ejemplo n.º 3
0
	def parse(self, text: str) -> ParseResult:
		arg = utils.get_element(text)
		try:
			enum = self.__enum_class[arg]
		except KeyError:
			raise InvalidEnumeration(arg) from None
		else:
			return ParseResult(enum, len(arg))
Ejemplo n.º 4
0
	def parse(self, text: str) -> ParseResult:
		arg = utils.get_element(text)
		if arg.lower() == 'true':
			value = True
		elif arg.lower() == 'false':
			value = False
		else:
			raise InvalidBoolean(arg)
		return ParseResult(value, len(arg))
Ejemplo n.º 5
0
	def _generate_suggestions(self, context: CommandContext) -> CommandSuggestions:
		"""
		Return a list of tuple (suggested command, suggested argument)
		"""
		def self_suggestions():
			return CommandSuggestions([CommandSuggestion(command_read_at_the_beginning, s) for s in self._get_suggestions(context)])

		suggestions = CommandSuggestions()
		# [!!aa bb cc] dd
		# read         suggested
		command_read_at_the_beginning = context.command_read
		if len(context.command_remaining) == 0:
			return self_suggestions()
		try:
			result = self.parse(context.command_remaining)
		except CommandSyntaxError:
			return self_suggestions()
		else:
			success_read = len(context.command) - len(context.command_remaining) + result.char_read  # type: int
			next_remaining = utils.remove_divider_prefix(context.command_remaining[result.char_read:])  # type: str
			total_read = len(context.command) - len(next_remaining)  # type: int

			with context.read_command(self, result, total_read):
				if self._requirement is not None and not self.__smart_callback(self._requirement, context.source, context):
					return CommandSuggestions()

				# Parsing finished
				if len(next_remaining) == 0:
					# total_read == success_read means DIVIDER does not exists at the end of the input string
					# in that case, ends at this current node
					if success_read == total_read:
						return self_suggestions()

				node = self if self._redirect_node is None else self._redirect_node
				# Check literal children first
				children_literal = node._children_literal.get(utils.get_element(next_remaining), [])
				for child_literal in children_literal:
					with context.enter_child(child_literal):
						suggestions.extend(child_literal._generate_suggestions(context))
				if len(children_literal) == 0:
					for literal_list in node._children_literal.values():
						for child_literal in literal_list:
							with context.enter_child(child_literal):
								suggestions.extend(child_literal._generate_suggestions(context))
					usages = []
					for child in node._children:
						with context.enter_child(child):
							suggestions.extend(child._generate_suggestions(context))
							if len(next_remaining) == 0:
								usages.append(child._get_usage())
					if len(next_remaining) == 0:
						suggestions.complete_hint = '|'.join(usages)
		return suggestions
Ejemplo n.º 6
0
    def execute_command(self, source: CommandSource, command: str):
        first_literal_element = utils.get_element(command)
        root_nodes = self.root_nodes.get(first_literal_element, [])
        if len(root_nodes
               ) > 0 and source.source_type == CommandSourceType.CONSOLE:
            # If this is a command, don't send it towards the server if it's from console input
            source.get_info().cancel_send_to_server()

        command_errors = []
        general_exc_info = []
        for node in root_nodes:
            try:
                node.execute(source, command)
            except CommandError as e:
                command_errors.append(e)
            except:
                general_exc_info.append(sys.exc_info())
        for exc_info in general_exc_info:
            self.logger.error(
                'Error when executing command "{}" with command source "{}"'.
                format(command, source),
                exc_info=exc_info)
        for error in command_errors:
            if not error.is_handled():
                translation_key = 'command_exception.{}'.format(
                    string_util.hump_to_underline(type(error).__name__))
                try:
                    error.set_translated_message(
                        translation_key, lambda key, args: self.mcdr_server.tr(
                            key, *args, allow_failure=False))
                except KeyError:
                    self.logger.debug(
                        'Fail to translated command error with key {}'.format(
                            translation_key),
                        option=DebugOption.COMMAND)
                source.reply(error.to_mc_color_text())
Ejemplo n.º 7
0
	def _traverse(self, command: str, source: CommandSource, purpose: TraversePurpose) -> None or List[CommandSuggestion]:
		first_literal_element = utils.get_element(command)
		plugin_root_nodes = self.root_nodes.get(first_literal_element, [])
		suggestions = CommandSuggestions()

		if purpose == TraversePurpose.EXECUTE and isinstance(source, InfoCommandSource):
			if len(plugin_root_nodes) > 0 and source.is_console:
				# If this is a command, don't send it towards the server if it's from console input
				source.get_info().cancel_send_to_server()

		if purpose == TraversePurpose.SUGGEST and len(plugin_root_nodes) == 0:
			return CommandSuggestions([CommandSuggestion('', literal) for literal in self.root_nodes.keys()])

		for plugin_root_node in plugin_root_nodes:
			plugin = plugin_root_node.plugin
			node = plugin_root_node.node
			try:
				with self.mcdr_server.plugin_manager.with_plugin_context(plugin):
					if purpose == TraversePurpose.EXECUTE:
						node.execute(source, command)
					elif purpose == TraversePurpose.SUGGEST:
						suggestions.extend(node.generate_suggestions(source, command))

			except CommandError as error:
				if not error.is_handled():
					translation_key = 'command_exception.{}'.format(string_util.hump_to_underline(type(error).__name__))
					try:
						error.set_message(self.__translate_command_error_header(translation_key, error))
					except KeyError:
						self.logger.debug('Fail to translated command error with key {}'.format(translation_key), option=DebugOption.COMMAND)
					source.reply(error.to_mc_color_text())
			except:
				self.logger.exception('Error when executing command "{}" with command source "{}" on {} registered by {}'.format(command, source, node, plugin))

		if purpose == TraversePurpose.SUGGEST:
			return suggestions
Ejemplo n.º 8
0
 def parse(self, text):
     arg = utils.get_element(text)
     if arg in self.literals:
         return ParseResult(None, len(arg))
     else:
         raise LiteralNotMatch('Invalid Argument', len(arg))
Ejemplo n.º 9
0
    def _execute_command(self, context: CommandContext) -> None:
        command = context.command  # type: str
        try:
            result = self.parse(context.command_remaining)
        except CommandSyntaxError as error:
            error.set_parsed_command(context.command_read)
            error.set_failed_command(
                context.command_read +
                context.command_remaining[:error.char_read])
            self.__raise_error(error, context)
        else:
            next_remaining = utils.remove_divider_prefix(
                context.command_remaining[result.char_read:])  # type: str
            total_read = len(command) - len(next_remaining)  # type: int

            with context.read_command(self, result, total_read):
                if self._requirement is not None:
                    if not self.__smart_callback(self._requirement,
                                                 context.source, context):
                        getter = self._requirement_failure_message_getter or (
                            lambda: None)
                        failure_message = self.__smart_callback(
                            getter, context.source, context)
                        self.__raise_error(
                            RequirementNotMet(context.command_read,
                                              context.command_read,
                                              failure_message), context)

                # Parsing finished
                if len(next_remaining) == 0:
                    if self._callback is not None:
                        self.__smart_callback(self._callback, context.source,
                                              context)
                    else:
                        self.__raise_error(
                            UnknownCommand(context.command_read,
                                           context.command_read), context)
                # Un-parsed command string remains
                else:
                    # Redirecting
                    node = self if self._redirect_node is None else self._redirect_node

                    argument_unknown = False
                    # No child at all
                    if not node.has_children():
                        argument_unknown = True
                    else:
                        # Pass the remaining command string to the children
                        next_literal = utils.get_element(next_remaining)
                        try:
                            # Check literal children first
                            literal_error = None
                            for child_literal in node._children_literal.get(
                                    next_literal, []):
                                try:
                                    with context.enter_child(child_literal):
                                        child_literal._execute_command(context)
                                    break
                                except CommandError as e:
                                    # it's ok for a direct literal node to fail
                                    # other literal might still have a chance to consume this command
                                    literal_error = e
                            else:  # All literal children fails
                                if literal_error is not None:
                                    raise literal_error
                                for child in node._children:
                                    with context.enter_child(child):
                                        child._execute_command(context)
                                    break
                                else:  # No argument child
                                    argument_unknown = True

                        except CommandError as error:
                            self.__handle_error(error, context,
                                                self._child_error_handlers)
                            raise error from None

                    if argument_unknown:
                        self.__raise_error(
                            UnknownArgument(context.command_read, command),
                            context)
Ejemplo n.º 10
0
 def parse(self, text):
     arg = utils.get_element(text)
     return self._check_length_in_range_and_return(arg, len(arg))