mcdreforged.command.builder.exception 源代码

from abc import ABC
from typing import Optional, Union

from mcdreforged.minecraft.rtext.text import RTextBase, RText, RColor
from mcdreforged.utils.types import MessageText


[文档] class CommandErrorBase(Exception, ABC): """ The base exception class for all command related errors Class inheriting tree:: CommandErrorBase ├── IllegalNodeOperation └── CommandError ├── UnknownCommand ├── UnknownArgument ├── RequirementNotMet └── CommandSyntaxError └── IllegalArgument ├── AbstractOutOfRange │ ├── NumberOutOfRange │ └── TextLengthOutOfRange ├── InvalidNumber ├── InvalidInteger ├── InvalidFloat ├── IllegalEscapesUsage ├── UnclosedQuotedString ├── EmptyText ├── InvalidBoolean └── InvalidEnumeration """ pass
[文档] class IllegalNodeOperation(CommandErrorBase): """ The operation is unsupported by this node """ pass
[文档] class CommandError(CommandErrorBase, ABC): """ The basic exception, for errors raised when parsing a command """ def __init__(self, message: MessageText, parsed_command: str, failed_command: str): # !!something wroooong command # [--parsed--|-error-] # [------failed------] self.__message: MessageText = message self._parsed_command: str = parsed_command self._failed_command: str = failed_command self.__handled: bool = False def __str__(self): return '{}: {}<--'.format(self.__message, self._failed_command) def to_rtext(self) -> RTextBase: return RTextBase.format( '{}: {}{}{}', RTextBase.from_any(self.__message).copy().set_color(RColor.red), RText(self.get_parsed_command(), RColor.dark_red), RText(self.get_error_segment(), RColor.red), RText('<--', RColor.dark_red) )
[文档] def get_error_data(self) -> tuple: """ Data that might be helpful for error report It will be used in error message str formatting """ return ()
def set_message(self, message: str): self.__message = message
[文档] def get_parsed_command(self) -> str: """ :return: A prefix of the input command that has been successfully parsed """ return self._parsed_command
[文档] def get_failed_command(self) -> str: """ :return: A prefix of the input command that is parsing when the failure occurs """ return self._failed_command
[文档] def get_error_segment(self) -> str: """ :return: The command segment that causes the error """ return self._failed_command[len(self._parsed_command):]
[文档] def set_handled(self) -> None: """ When handling the command error by error listener on the command tree node, you can use this method to tell MCDR the command error has been handled so MCDR will not display the default command failure message to the command source like ``Unknown argument: !!MCDR reload this<--`` It won't make any difference to the command node tree execution, but it might be useful for outer error handlers """ self.__handled = True
def is_handled(self) -> bool: return self.__handled
[文档] class UnknownCommand(CommandError): """ When the command finishes parsing, but current node doesn't have a command callback function """ def __init__(self, parsed_command, failed_command): super().__init__('Unknown Command', parsed_command, failed_command)
[文档] class UnknownArgument(CommandError): """ When there's remaining command string, but there's no matched children command nodes """ def __init__(self, parsed_command: str, failed_command: str): super().__init__('Unknown Argument', parsed_command, failed_command)
class UnknownRootArgument(UnknownArgument): """ The same as :class:`UnknownArgument`, but it fails to match at root node Internal-use only :meta private: """ pass
[文档] class RequirementNotMet(CommandError): """ The specified requirement for the command source to enter this node is not met """ __NO_REASON = RText('Requirement not met') def __init__(self, parsed_command: str, failed_command: str, reason: Optional[MessageText]): self.__reason: MessageText = reason if reason is not None else self.__NO_REASON super().__init__(self.__reason, parsed_command, failed_command) def has_custom_reason(self) -> bool: return self.__reason is not self.__NO_REASON def get_reason(self) -> MessageText: return self.__reason def get_error_data(self) -> tuple: return (self.get_reason(),)
# ----------------- # Syntax things # -----------------
[文档] class CommandSyntaxError(CommandError, ABC): """ The basic exception for command parsing error """ def __init__(self, message: MessageText, char_read: Union[int, str]): super().__init__(message, '', '?' if isinstance(char_read, int) else char_read) self.message = message self.char_read = char_read if isinstance(char_read, int) else len(char_read) def set_parsed_command(self, parsed_command): self._parsed_command = parsed_command def set_failed_command(self, failed_command): self._failed_command = failed_command
[文档] class IllegalArgument(CommandSyntaxError, ABC): """ The basic exception for argument parsing error, usually caused by wrong argument syntax """ pass
class LiteralNotMatch(CommandSyntaxError): """ Used by Literal node parsing failure for fail-soft Internal-use only :meta private: """ pass
[文档] class AbstractOutOfRange(IllegalArgument, ABC): """ The basic exception for out-of-range like argument parsing error """ def __init__(self, message: MessageText, char_read: Union[int, str], value, range_l, range_r): """ :param value: The actual value :param range_l: The left boundary :param range_r: The right boundary """ super().__init__(message, char_read) self.__value = value self.__range_l = range_l self.__range_r = range_r @classmethod def get_boundary_text(cls, value) -> str: return str(value) if value is not None else '/' def get_error_data(self) -> tuple: return self.__value, self.get_boundary_text(self.__range_l), self.get_boundary_text(self.__range_r)
# Number things
[文档] class NumberOutOfRange(AbstractOutOfRange): """ The parsed number value is out of the restriction range """ def __init__(self, char_read: Union[int, str], value, range_l, range_r): super().__init__('Value out of range [{}, {}]'.format(self.get_boundary_text(range_l), self.get_boundary_text(range_r)), char_read, value, range_l, range_r)
[文档] class InvalidNumber(IllegalArgument): """ The parsed value is not a valid number """ def __init__(self, char_read: Union[int, str]): super().__init__('Invalid number', char_read)
[文档] class InvalidInteger(IllegalArgument): """ The parsed value is not a valid integer """ def __init__(self, char_read: Union[int, str]): super().__init__('Invalid integer', char_read)
[文档] class InvalidFloat(IllegalArgument): """ The parsed value is not a valid float """ def __init__(self, char_read: Union[int, str]): super().__init__('Invalid float', char_read)
# Text things
[文档] class TextLengthOutOfRange(AbstractOutOfRange): """ The length of the given text is out of the restriction range """ def __init__(self, char_read: Union[int, str], value, range_l, range_r): super().__init__('Text length {} out of range [{}, {}]'.format(value, self.get_boundary_text(range_l), self.get_boundary_text(range_r)), char_read, value, range_l, range_r)
[文档] class IllegalEscapesUsage(IllegalArgument): """ The text contains illegal ``\\`` usage """ def __init__(self, char_read: Union[int, str]): super().__init__('Illegal usage of escapes', char_read)
[文档] class UnclosedQuotedString(IllegalArgument): """ The quote is unclosed """ def __init__(self, char_read: Union[int, str]): super().__init__('Unclosed quoted string', char_read)
[文档] class EmptyText(IllegalArgument): """ The text is empty, which is not allowed """ def __init__(self, char_read: Union[int, str]): super().__init__('Empty text is not allowed', char_read)
# Other Arguments
[文档] class InvalidBoolean(IllegalArgument): """ The parsed value is not a valid boolean """ def __init__(self, char_read: Union[int, str]): super().__init__('Invalid boolean', char_read)
[文档] class InvalidEnumeration(IllegalArgument): """ The parsed value is not a valid Enum """ def __init__(self, char_read: Union[int, str]): super().__init__('Invalid enumeration', char_read)