Example #1
0
 def _string_less_than_equals_path(self, data: Any, variable_value: str) -> bool:
     string_less_than_equals = self.data_test_expression.expression.apply(data)  # type: ignore
     if not (isinstance(string_less_than_equals, str)):  # pragma: no cover
         raise AWSStepFuncsValueError(
             "string_less_than_equals_path must evaluate to a string value"
         )
     return variable_value <= string_less_than_equals
Example #2
0
    def __init__(
        self,
        *,
        start_state: AbstractState,
        output_path: Union[str, Path] = "state_machine.gif",
    ):
        """Initialize a state machine visualization.

        Make sure that if you specify the output path for the visualization that it
        ends with `.gif`; otherwise, there will be an error.

        Args:
            start_state: The starting state of the state machine, used to
                determine all possible state transitions.
            output_path: What path to save the visualization GIF to.

        Raises:
            AWSStepFuncsValueError: Raised when the output path doesn't end with `.gif`.
        """
        self.animation = gvanim.Animation()
        self._build_state_graph(start_state)

        if not str(output_path).endswith(".gif"):
            raise AWSStepFuncsValueError(
                'Visualization output path must end with ".gif"'
            )

        self.output_path = Path(output_path)
Example #3
0
    def _validate(self) -> None:
        """Validate a Reference Path for Amazon States Language.

        Raises:
            AWSStepFuncsValueError: Raised when Reference Path is an empty string or does not
                begin with a "$".
            AWSStepFuncsValueError: Raised when the Reference Path has an unsupported operator (an
                operator that Amazon States Language does not support).
        """
        if not self.reference_path or str(self.reference_path)[0] != "$":
            raise AWSStepFuncsValueError('Reference Path must begin with "$"')

        unsupported_operators = {"@", "..", ",", ":", "?", "*"}
        for operator in unsupported_operators:
            if operator in str(self.reference_path):
                raise AWSStepFuncsValueError(
                    f'Unsupported Reference Path operator: "{operator}"'
                )
Example #4
0
    def __init__(
        self,
        *args: Any,
        seconds: Optional[int] = None,
        timestamp: Optional[datetime] = None,
        seconds_path: Optional[str] = None,
        timestamp_path: Optional[str] = None,
        **kwargs: Any,
    ):
        """Initialize a Wait State.

        Args:
            args: Args to pass to parent classes.
            seconds: The number of seconds to wait.
            timestamp: Wait until the specified time.
            seconds_path: A Reference Path to the number of seconds to wait.
            timestamp_path: A Reference Path to the timestamp to wait until.
            kwargs: Kwargs to pass to parent classes.

        Raises:
            AWSStepFuncsValueError: Raised when not exactly one is defined: seconds,
                timestamp, seconds_path, timestamp_path.
        """
        super().__init__(*args, **kwargs)

        if (sum(
                bool(variable) for variable in
            [seconds, timestamp, seconds_path, timestamp_path]) != 1):
            raise AWSStepFuncsValueError(
                "Exactly one must be defined: seconds, timestamp, seconds_path, timestamp_path"
            )

        if seconds and not (seconds > 0):
            raise AWSStepFuncsValueError("seconds must be greater than zero")

        self.seconds = seconds
        self.timestamp = timestamp
        self.seconds_path = ReferencePath(
            seconds_path) if seconds_path else None
        self.timestamp_path = ReferencePath(
            timestamp_path) if timestamp_path else None
Example #5
0
 def _numeric_greater_than_path(
     self, data: Any, variable_value: Union[float, int]
 ) -> bool:
     numeric_greater_than = self.data_test_expression.expression.apply(data)  # type: ignore
     if not (
         isinstance(numeric_greater_than, int)
         or isinstance(numeric_greater_than, float)
     ):
         raise AWSStepFuncsValueError(
             "numeric_greater_than_path must evaluate to a numeric value"
         )
     return variable_value > numeric_greater_than
Example #6
0
    def __init__(
        self,
        error_equals: List[str],
        interval_seconds: Optional[int] = None,
        backoff_rate: Optional[float] = None,
        max_attempts: Optional[int] = None,
    ) -> None:
        """Initialize a Retrier.

        Args:
            error_equals: A list of error names.
            interval_seconds: The number of seconds before the first retry
                attempt. Defaults to 1 if not specified.
            backoff_rate: A number which is the multiplier that increases the
                retry interval on each attempt. Defaults to 2.0 if not specified.
            max_attempts: The maximum number of retry to attempt. Defaults to 3
                if not specified. A value of zero means that the error should never
                be retried.

        Raises:
            AWSStepFuncsValueError: Raised when interval_seconds is negative.
            AWSStepFuncsValueError: Raised when backoff_rate is less than 1.0.
            AWSStepFuncsValueError: Raised when max_attempts is negative.
        """
        if interval_seconds and interval_seconds <= 0:  # pragma: no cover
            raise AWSStepFuncsValueError(
                "interval_seconds must be a positive integer")
        if backoff_rate and backoff_rate < 1:  # pragma: no cover
            raise AWSStepFuncsValueError(
                "backoff_rate must be greater than or equal to 1.0")
        if max_attempts is not None and max_attempts < 0:  # pragma: no cover
            raise AWSStepFuncsValueError(
                "max_attempts must be zero or a positive integer")

        super().__init__(error_equals)
        self.interval_seconds = interval_seconds
        self.backoff_rate = backoff_rate
        self.max_attempts = max_attempts
Example #7
0
    def __rshift__(self, _: AbstractState, /) -> AbstractState:
        """Overload >> operator to set state execution order.

        You cannot set a next state on a ChoiceState, SucceedState, or FailState
        as they are terminal states.

        Args:
            _: The other state besides self.

        Raises:
            AWSStepFuncsValueError: Raised when trying to set next state on a terminal
                state.
        """
        raise AWSStepFuncsValueError(
            f"{self.__class__.__name__} cannot have a next state")
Example #8
0
    def _validate_result_selector(result_selector: Dict[str, str]) -> None:
        """Validate result selector.

        Args:
            result_selector: The result selector to validate.

        Raises:
            AWSStepFuncsValueError: Raised when a key doesn't end with ".$".
            AWSStepFuncsValueError: Raised when a ReferencePath is invalid.
        """
        for key, reference_path in result_selector.items():
            if not key[-2:] == ".$":
                raise AWSStepFuncsValueError(
                    "All resource selector keys must end with .$"
                )

            # TODO: Check if ReferencePath(...) is being called twice
            ReferencePath(reference_path)
Example #9
0
    def __init__(self, name: str, comment: Optional[str] = None):
        """Initialize subclasses.

        Args:
            name: The name of the state. Must be unique within the state machine
                and its length cannot exceed 128 characters.
            comment: A human-readable description of the state.

        Raises:
            AWSStepFuncsValueError: Raised when the state name exceeds 128 characters.
        """
        if len(name) > MAX_STATE_NAME_LENGTH:
            raise AWSStepFuncsValueError(
                f"State name cannot exceed {MAX_STATE_NAME_LENGTH} characters"
            )

        self.name = name
        self.comment = comment
        self.next_state: Optional[AbstractState] = None
        self.print: Printer  # Used for simulations
Example #10
0
    def __init__(self, variable: str, **data_test_expression: Any):
        """Initialize a Choice Rule.

        Args:
            variable: The Reference Path to a variable in the state input.
            data_test_expression: The data-test expression to use.

        Raises:
            AWSStepFuncsValueError: Raised when there is not exactly one data-test
                expression defined.
        """
        self.variable = ReferencePath(variable)

        if len(data_test_expression) != 1:
            raise AWSStepFuncsValueError(
                "Exactly one data-test expression must be defined"
            )

        self.data_test_expression = DataTestExpression(
            *list(data_test_expression.items())[0]
        )