From 88a11346576d740983fe648e62d88e5ba780e38d Mon Sep 17 00:00:00 2001 From: Iain Bullard Date: Fri, 31 Jul 2020 17:46:48 +0100 Subject: [PATCH] Fix DynamoDb2 ExpressionAttributeNames can start with a number (#3206) When using pynamodb's support for transactions it makes use of of ExpressionAttributeNames that look like #0 #1 etc. According to https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ExpressionAttributeNames.html And when testing against dynamodb-local these work without issue, however, when testing with moto they fail. --- moto/dynamodb2/parsing/tokens.py | 2 +- .../test_dynamodb_expression_tokenizer.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/moto/dynamodb2/parsing/tokens.py b/moto/dynamodb2/parsing/tokens.py index 4fbb7883..34c3151e 100644 --- a/moto/dynamodb2/parsing/tokens.py +++ b/moto/dynamodb2/parsing/tokens.py @@ -109,7 +109,7 @@ class ExpressionTokenizer(object): @classmethod def is_expression_attribute(cls, input_string): - return re.compile("^[a-zA-Z][a-zA-Z0-9_]*$").match(input_string) is not None + return re.compile("^[a-zA-Z0-9][a-zA-Z0-9_]*$").match(input_string) is not None @classmethod def is_expression_attribute_name(cls, input_string): diff --git a/tests/test_dynamodb2/test_dynamodb_expression_tokenizer.py b/tests/test_dynamodb2/test_dynamodb_expression_tokenizer.py index 3330d431..ddfb81d1 100644 --- a/tests/test_dynamodb2/test_dynamodb_expression_tokenizer.py +++ b/tests/test_dynamodb2/test_dynamodb_expression_tokenizer.py @@ -219,6 +219,18 @@ def test_expression_tokenizer_single_set_action_attribute_name_valid_key(): ] +def test_expression_tokenizer_single_set_action_attribute_name_leading_number(): + set_action = "SET attr=#0" + 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, "#0"), + ] + + def test_expression_tokenizer_just_a_pipe(): set_action = "|" try: