diff --git a/moto/dynamodb/parsing/tokens.py b/moto/dynamodb/parsing/tokens.py index 3ccc9f8bd..fbb46d66f 100644 --- a/moto/dynamodb/parsing/tokens.py +++ b/moto/dynamodb/parsing/tokens.py @@ -116,8 +116,9 @@ class ExpressionTokenizer(object): An expression attribute name must begin with a pound sign (#), and be followed by one or more alphanumeric characters. """ - return input_string.startswith("#") and cls.is_expression_attribute( - input_string[1:] + return ( + input_string.startswith("#") + and re.compile("^[a-zA-Z0-9_]+$").match(input_string[1:]) is not None ) @classmethod @@ -182,8 +183,9 @@ class ExpressionTokenizer(object): def _make_list(self) -> List[Token]: """ - Just go through characters if a character is not a token boundary stage it for adding it as a grouped token - later if it is a tokenboundary process staged characters and then process the token boundary as well. + Just go through characters + if a character is not a token boundary, stage it for adding it as a grouped token later + if it is a tokenboundary, process staged characters, and then process the token boundary as well. """ for character in self.input_expression_str: if not self.is_possible_token_boundary(character): diff --git a/tests/test_dynamodb/test_dynamodb_expression_tokenizer.py b/tests/test_dynamodb/test_dynamodb_expression_tokenizer.py index bc4342dbb..9a7740cf9 100644 --- a/tests/test_dynamodb/test_dynamodb_expression_tokenizer.py +++ b/tests/test_dynamodb/test_dynamodb_expression_tokenizer.py @@ -231,6 +231,18 @@ def test_expression_tokenizer_single_set_action_attribute_name_leading_number(): ] +def test_expression_tokenizer_single_set_action_attribute_name_leading_underscore(): + set_action = "SET attr=#_sth" + token_list = ExpressionTokenizer.make_list(set_action) + assert token_list == [ + Token(Token.ATTRIBUTE, "SET"), + Token(Token.WHITESPACE, " "), + Token(Token.ATTRIBUTE, "attr"), + Token(Token.EQUAL_SIGN, "="), + Token(Token.ATTRIBUTE_NAME, "#_sth"), + ] + + def test_expression_tokenizer_just_a_pipe(): set_action = "|" try: