diff --git a/moto/dynamodb/models/__init__.py b/moto/dynamodb/models/__init__.py
--- a/moto/dynamodb/models/__init__.py
+++ b/moto/dynamodb/models/__init__.py
@@ -301,11 +301,11 @@ def get_item(
         self,
         table_name: str,
         keys: Dict[str, Any],
-        projection_expression: Optional[str] = None,
+        projection_expressions: Optional[List[List[str]]] = None,
     ) -> Optional[Item]:
         table = self.get_table(table_name)
         hash_key, range_key = self.get_keys_value(table, keys)
-        return table.get_item(hash_key, range_key, projection_expression)
+        return table.get_item(hash_key, range_key, projection_expressions)
 
     def query(
         self,
@@ -316,7 +316,7 @@ def query(
         limit: int,
         exclusive_start_key: Dict[str, Any],
         scan_index_forward: bool,
-        projection_expression: Optional[str],
+        projection_expressions: Optional[List[List[str]]],
         index_name: Optional[str] = None,
         expr_names: Optional[Dict[str, str]] = None,
         expr_values: Optional[Dict[str, str]] = None,
@@ -339,7 +339,7 @@ def query(
             limit,
             exclusive_start_key,
             scan_index_forward,
-            projection_expression,
+            projection_expressions,
             index_name,
             filter_expression_op,
             **filter_kwargs,
@@ -355,7 +355,7 @@ def scan(
         expr_names: Dict[str, Any],
         expr_values: Dict[str, Any],
         index_name: str,
-        projection_expression: Optional[str],
+        projection_expression: Optional[List[List[str]]],
     ) -> Tuple[List[Item], int, Optional[Dict[str, Any]]]:
         table = self.get_table(table_name)
 
diff --git a/moto/dynamodb/models/dynamo_type.py b/moto/dynamodb/models/dynamo_type.py
--- a/moto/dynamodb/models/dynamo_type.py
+++ b/moto/dynamodb/models/dynamo_type.py
@@ -418,13 +418,12 @@ def update_with_attribute_updates(self, attribute_updates: Dict[str, Any]) -> No
                     f"{action} action not support for update_with_attribute_updates"
                 )
 
-    def project(self, projection_expression: str) -> "Item":
+    def project(self, projection_expressions: List[List[str]]) -> "Item":
         # Returns a new Item with only the dictionary-keys that match the provided projection_expression
         # Will return an empty Item if the expression does not match anything
         result: Dict[str, Any] = dict()
-        expressions = [x.strip() for x in projection_expression.split(",")]
-        for expr in expressions:
-            x = find_nested_key(expr.split("."), self.to_regular_json())
+        for expr in projection_expressions:
+            x = find_nested_key(expr, self.to_regular_json())
             merge_dicts(result, x)
 
         return Item(
diff --git a/moto/dynamodb/models/table.py b/moto/dynamodb/models/table.py
--- a/moto/dynamodb/models/table.py
+++ b/moto/dynamodb/models/table.py
@@ -50,12 +50,18 @@ def project(self, item: Item) -> Item:
             ]
 
             if projection_type == "KEYS_ONLY":
-                item = item.project(",".join(key_attributes))
+                # 'project' expects lists of lists of strings
+                # project([["attr1"], ["nested", "attr2"]]
+                #
+                # In our case, we need to convert
+                # ["key1", "key2"]
+                # into
+                # [["key1"], ["key2"]]
+                item = item.project([[attr] for attr in key_attributes])
             elif projection_type == "INCLUDE":
-                allowed_attributes = key_attributes + self.projection.get(
-                    "NonKeyAttributes", []
-                )
-                item = item.project(",".join(allowed_attributes))
+                allowed_attributes = key_attributes
+                allowed_attributes.extend(self.projection.get("NonKeyAttributes", []))
+                item = item.project([[attr] for attr in allowed_attributes])
             # ALL is handled implicitly by not filtering
         return item
 
@@ -592,7 +598,7 @@ def get_item(
         self,
         hash_key: DynamoType,
         range_key: Optional[DynamoType] = None,
-        projection_expression: Optional[str] = None,
+        projection_expression: Optional[List[List[str]]] = None,
     ) -> Optional[Item]:
         if self.has_range_key and not range_key:
             raise MockValidationException(
@@ -637,7 +643,7 @@ def query(
         limit: int,
         exclusive_start_key: Dict[str, Any],
         scan_index_forward: bool,
-        projection_expression: Optional[str],
+        projection_expressions: Optional[List[List[str]]],
         index_name: Optional[str] = None,
         filter_expression: Any = None,
         **filter_kwargs: Any,
@@ -754,8 +760,8 @@ def conv(x: DynamoType) -> Any:
         if filter_expression is not None:
             results = [item for item in results if filter_expression.expr(item)]
 
-        if projection_expression:
-            results = [r.project(projection_expression) for r in results]
+        if projection_expressions:
+            results = [r.project(projection_expressions) for r in results]
 
         return results, scanned_count, last_evaluated_key
 
@@ -799,7 +805,7 @@ def scan(
         exclusive_start_key: Dict[str, Any],
         filter_expression: Any = None,
         index_name: Optional[str] = None,
-        projection_expression: Optional[str] = None,
+        projection_expression: Optional[List[List[str]]] = None,
     ) -> Tuple[List[Item], int, Optional[Dict[str, Any]]]:
         results = []
         scanned_count = 0
diff --git a/moto/dynamodb/responses.py b/moto/dynamodb/responses.py
--- a/moto/dynamodb/responses.py
+++ b/moto/dynamodb/responses.py
@@ -556,11 +556,11 @@ def get_item(self) -> str:
                 )
 
         expression_attribute_names = expression_attribute_names or {}
-        projection_expression = self._adjust_projection_expression(
+        projection_expressions = self._adjust_projection_expression(
             projection_expression, expression_attribute_names
         )
 
-        item = self.dynamodb_backend.get_item(name, key, projection_expression)
+        item = self.dynamodb_backend.get_item(name, key, projection_expressions)
         if item:
             item_dict = item.describe_attrs(attributes=None)
             return dynamo_json_dump(item_dict)
@@ -608,14 +608,14 @@ def batch_get_item(self) -> str:
                 "ExpressionAttributeNames", {}
             )
 
-            projection_expression = self._adjust_projection_expression(
+            projection_expressions = self._adjust_projection_expression(
                 projection_expression, expression_attribute_names
             )
 
             results["Responses"][table_name] = []
             for key in keys:
                 item = self.dynamodb_backend.get_item(
-                    table_name, key, projection_expression
+                    table_name, key, projection_expressions
                 )
                 if item:
                     # A single operation can retrieve up to 16 MB of data [and] returns a partial result if the response size limit is exceeded
@@ -652,7 +652,7 @@ def query(self) -> str:
         filter_expression = self._get_filter_expression()
         expression_attribute_values = self.body.get("ExpressionAttributeValues", {})
 
-        projection_expression = self._adjust_projection_expression(
+        projection_expressions = self._adjust_projection_expression(
             projection_expression, expression_attribute_names
         )
 
@@ -720,7 +720,7 @@ def query(self) -> str:
             limit,
             exclusive_start_key,
             scan_index_forward,
-            projection_expression,
+            projection_expressions,
             index_name=index_name,
             expr_names=expression_attribute_names,
             expr_values=expression_attribute_values,
@@ -743,27 +743,24 @@ def query(self) -> str:
 
     def _adjust_projection_expression(
         self, projection_expression: Optional[str], expr_attr_names: Dict[str, str]
-    ) -> Optional[str]:
+    ) -> List[List[str]]:
+        """
+        lvl1.lvl2.attr1,lvl1.attr2 --> [["lvl1", "lvl2", "attr1"], ["lvl1", "attr2]]
+        """
+
         def _adjust(expression: str) -> str:
-            return (
-                expr_attr_names[expression]
-                if expression in expr_attr_names
-                else expression
-            )
+            return (expr_attr_names or {}).get(expression, expression)
 
         if projection_expression:
             expressions = [x.strip() for x in projection_expression.split(",")]
             for expression in expressions:
                 check_projection_expression(expression)
-            if expr_attr_names:
-                return ",".join(
-                    [
-                        ".".join([_adjust(expr) for expr in nested_expr.split(".")])
-                        for nested_expr in expressions
-                    ]
-                )
+            return [
+                [_adjust(expr) for expr in nested_expr.split(".")]
+                for nested_expr in expressions
+            ]
 
-        return projection_expression
+        return []
 
     @include_consumed_capacity()
     def scan(self) -> str:
@@ -786,7 +783,7 @@ def scan(self) -> str:
         limit = self.body.get("Limit")
         index_name = self.body.get("IndexName")
 
-        projection_expression = self._adjust_projection_expression(
+        projection_expressions = self._adjust_projection_expression(
             projection_expression, expression_attribute_names
         )
 
@@ -800,7 +797,7 @@ def scan(self) -> str:
                 expression_attribute_names,
                 expression_attribute_values,
                 index_name,
-                projection_expression,
+                projection_expressions,
             )
         except ValueError as err:
             raise MockValidationException(f"Bad Filter Expression: {err}")

The Dynamo item has `software`, but the query looks for `packages` - could that be the problem?

Note that I haven't verified this in Moto.
> The Dynamo item has `software`, but the query looks for `packages` - could that be the problem?
> 
> Note that I haven't verified this in Moto.

No sorry, that was a mistake by me when I was constructing the example.
Ah, found it. Moto doesn't play nice with attributes that contain a `.` - presumably because it assumes that it should be a map. Marking it as a bug!
Alright, thank you so much for the quick reply. 
diff --git a/tests/test_dynamodb/models/test_item.py b/tests/test_dynamodb/models/test_item.py
--- a/tests/test_dynamodb/models/test_item.py
+++ b/tests/test_dynamodb/models/test_item.py
@@ -34,17 +34,17 @@ def _project(self, expression, result):
         assert x == y
 
     def test_find_nothing(self):
-        self._project("", result={})
+        self._project([[""]], result={})
 
     def test_find_unknown_key(self):
-        self._project("unknown", result={})
+        self._project([["unknown"]], result={})
 
     def test_project_single_key_string(self):
-        self._project("simplestring", result={"simplestring": "val"})
+        self._project([["simplestring"]], result={"simplestring": "val"})
 
     def test_project_single_key_dict(self):
         self._project(
-            "nesteddict",
+            [["nesteddict"]],
             result={
                 "nesteddict": {
                     "level21": {"ll31": "val", "ll32": "val"},
@@ -59,31 +59,31 @@ def test_project_single_key_dict(self):
 
     def test_project_nested_key(self):
         self._project(
-            "nesteddict.level21",
+            [["nesteddict", "level21"]],
             result={"nesteddict": {"level21": {"ll31": "val", "ll32": "val"}}},
         )
 
     def test_project_multi_level_nested_key(self):
         self._project(
-            "nesteddict.level21.ll32",
+            [["nesteddict", "level21", "ll32"]],
             result={"nesteddict": {"level21": {"ll32": "val"}}},
         )
 
     def test_project_nested_key__partial_fix(self):
-        self._project("nesteddict.levelunknown", result={})
+        self._project([["nesteddict", "levelunknown"]], result={})
 
     def test_project_nested_key__partial_fix2(self):
-        self._project("nesteddict.unknown.unknown2", result={})
+        self._project([["nesteddict", "unknown", "unknown2"]], result={})
 
     def test_list_index(self):
         self._project(
-            "rootlist[0]",
+            [["rootlist[0]"]],
             result={"rootlist": [{"ll21": {"ll31": "val", "ll32": "val"}}]},
         )
 
     def test_nested_list_index(self):
         self._project(
-            "nesteddict.nestedlist[1]",
+            [["nesteddict", "nestedlist[1]"]],
             result={
                 "nesteddict": {"nestedlist": [{"ll22": {"ll31": "val", "ll32": "val"}}]}
             },
@@ -91,16 +91,16 @@ def test_nested_list_index(self):
 
     def test_nested_obj_in_list(self):
         self._project(
-            "nesteddict.nestedlist[1].ll22.ll31",
+            [["nesteddict", "nestedlist[1]", "ll22", "ll31"]],
             result={"nesteddict": {"nestedlist": [{"ll22": {"ll31": "val"}}]}},
         )
 
     def test_list_unknown_indexes(self):
-        self._project("nesteddict.nestedlist[25]", result={})
+        self._project([["nesteddict", "nestedlist[25]"]], result={})
 
     def test_multiple_projections(self):
         self._project(
-            "nesteddict.nestedlist[1].ll22,rootlist[0]",
+            [["nesteddict", "nestedlist[1]", "ll22"], ["rootlist[0]"]],
             result={
                 "nesteddict": {
                     "nestedlist": [{"ll22": {"ll31": "val", "ll32": "val"}}]
diff --git a/tests/test_dynamodb/test_dynamodb.py b/tests/test_dynamodb/test_dynamodb.py
--- a/tests/test_dynamodb/test_dynamodb.py
+++ b/tests/test_dynamodb/test_dynamodb.py
@@ -886,7 +886,7 @@ def test_nested_projection_expression_using_get_item_with_attr_expression():
             "forum_name": "key1",
             "nested": {
                 "level1": {"id": "id1", "att": "irrelevant"},
-                "level2": {"id": "id2", "include": "all"},
+                "level.2": {"id": "id2", "include": "all"},
                 "level3": {
                     "id": "irrelevant",
                     "children": [{"Name": "child_a"}, {"Name": "child_b"}],
@@ -907,10 +907,10 @@ def test_nested_projection_expression_using_get_item_with_attr_expression():
     result = table.get_item(
         Key={"forum_name": "key1"},
         ProjectionExpression="#nst.level1.id, #nst.#lvl2",
-        ExpressionAttributeNames={"#nst": "nested", "#lvl2": "level2"},
+        ExpressionAttributeNames={"#nst": "nested", "#lvl2": "level.2"},
     )["Item"]
     assert result == {
-        "nested": {"level1": {"id": "id1"}, "level2": {"id": "id2", "include": "all"}}
+        "nested": {"level1": {"id": "id1"}, "level.2": {"id": "id2", "include": "all"}}
     }
     # Assert actual data has not been deleted
     result = table.get_item(Key={"forum_name": "key1"})["Item"]
@@ -919,7 +919,7 @@ def test_nested_projection_expression_using_get_item_with_attr_expression():
         "forum_name": "key1",
         "nested": {
             "level1": {"id": "id1", "att": "irrelevant"},
-            "level2": {"id": "id2", "include": "all"},
+            "level.2": {"id": "id2", "include": "all"},
             "level3": {
                 "id": "irrelevant",
                 "children": [{"Name": "child_a"}, {"Name": "child_b"}],

DynamoDB: special characters in get_item() projection expression not handled correctly
Hi!

I have a nested attribute inside a dynamodb table like so:
````json
{
    "device": {
        "N": "123456"
    },
    "software": {
        "M": {
            "python3.10": {
                "M": {
                    "lorem": {
                        "S": "asdf"
                    },
                    "ipsum": {
                        "S": "asdf"
                    }
                }
            },
            "curl": {
                "M": {
                    "lorem": {
                        "S": "asdf"
                    },
                    "ipsum": {
                        "S": "asdf"
                    }
                }
            }
        }
    }
}
````
Now I want to use the `get_item()` function of a dynamodb resource to only get the data of the "python3.10" entry:

````python
result = table.get_item(
    Key={"device": 123456},
    ProjectionExpression="software.#python3_10",
    ExpressionAttributeNames={"#python3_10": "python3.10"}
)
````
But I only get an empty result set (`Item: {}`).
_It works when I do this via the AWS CLI_. That leads me to believe, that this might be a moto issue. I would be very happy if someone could verify this assumption.

Thanks in advance,
Mats

tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_project_single_key_dict tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_list_unknown_indexes tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_project_nested_key tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_find_nothing tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_find_unknown_key tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_project_single_key_string tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_list_index tests/test_dynamodb/test_dynamodb.py::test_nested_projection_expression_using_get_item_with_attr_expression tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_nested_obj_in_list tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_project_multi_level_nested_key tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_project_nested_key__partial_fix tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_nested_list_index tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_multiple_projections tests/test_dynamodb/models/test_item.py::TestFindNestedKeys::test_project_nested_key__partial_fix2
tests/test_dynamodb/test_dynamodb.py::test_remove_list_index__remove_existing_nested_index tests/test_dynamodb/test_dynamodb.py::test_basic_projection_expressions_using_query_with_attr_expression_names tests/test_dynamodb/test_dynamodb.py::test_transact_write_items_put_conditional_expressions_return_values_on_condition_check_failure_all_old tests/test_dynamodb/test_dynamodb.py::test_describe_backup_for_non_existent_backup_raises_error tests/test_dynamodb/test_dynamodb.py::test_update_item_with_list tests/test_dynamodb/test_dynamodb.py::test_describe_continuous_backups_errors tests/test_dynamodb/test_dynamodb.py::test_describe_missing_table_boto3 tests/test_dynamodb/test_dynamodb.py::test_transact_write_items_delete tests/test_dynamodb/test_dynamodb.py::test_remove_list_index__remove_existing_index tests/test_dynamodb/test_dynamodb.py::test_dynamodb_update_item_fails_on_string_sets tests/test_dynamodb/test_dynamodb.py::test_projection_expression_execution_order tests/test_dynamodb/test_dynamodb.py::test_update_item_with_attribute_in_right_hand_side_and_operation tests/test_dynamodb/test_dynamodb.py::test_transact_write_items_conditioncheck_passes tests/test_dynamodb/test_dynamodb.py::test_basic_projection_expression_using_get_item tests/test_dynamodb/test_dynamodb.py::test_list_table_tags_empty tests/test_dynamodb/test_dynamodb.py::test_create_backup_for_non_existent_table_raises_error tests/test_dynamodb/test_dynamodb.py::test_update_expression_with_plus_in_attribute_name tests/test_dynamodb/test_dynamodb.py::test_scan_filter2 tests/test_dynamodb/test_dynamodb.py::test_describe_backup tests/test_dynamodb/test_dynamodb.py::test_batch_write_item tests/test_dynamodb/test_dynamodb.py::test_transact_write_items_delete_with_successful_condition_expression tests/test_dynamodb/test_dynamodb.py::test_query_invalid_table tests/test_dynamodb/test_dynamodb.py::test_delete_backup tests/test_dynamodb/test_dynamodb.py::test_nested_projection_expression_using_query tests/test_dynamodb/test_dynamodb.py::test_transact_get_items_should_return_empty_map_for_non_existent_item tests/test_dynamodb/test_dynamodb.py::test_update_supports_list_append_maps tests/test_dynamodb/test_dynamodb.py::test_update_item_add_to_num_set_using_legacy_attribute_updates tests/test_dynamodb/test_dynamodb.py::test_update_supports_nested_update_if_nested_value_not_exists tests/test_dynamodb/test_dynamodb.py::test_index_with_unknown_attributes_should_fail tests/test_dynamodb/test_dynamodb.py::test_update_supports_nested_list_append tests/test_dynamodb/test_dynamodb.py::test_update_item_atomic_counter_from_zero tests/test_dynamodb/test_dynamodb.py::test_update_item_if_original_value_is_none tests/test_dynamodb/test_dynamodb.py::test_filter_expression_execution_order tests/test_dynamodb/test_dynamodb.py::test_delete_item tests/test_dynamodb/test_dynamodb.py::test_list_tables_paginated tests/test_dynamodb/test_dynamodb.py::test_query_gsi_with_range_key tests/test_dynamodb/test_dynamodb.py::test_valid_transact_get_items tests/test_dynamodb/test_dynamodb.py::test_describe_continuous_backups tests/test_dynamodb/test_dynamodb.py::test_remove_list_index__remove_existing_double_nested_index tests/test_dynamodb/test_dynamodb.py::test_non_existing_attribute_should_raise_exception tests/test_dynamodb/test_dynamodb.py::test_scan_by_non_exists_index tests/test_dynamodb/test_dynamodb.py::test_update_supports_list_append_with_nested_if_not_exists_operation tests/test_dynamodb/test_dynamodb.py::test_put_empty_item tests/test_dynamodb/test_dynamodb.py::test_gsi_lastevaluatedkey tests/test_dynamodb/test_dynamodb.py::test_query_catches_when_no_filters tests/test_dynamodb/test_dynamodb.py::test_restore_table_to_point_in_time_raises_error_when_dest_exist tests/test_dynamodb/test_dynamodb.py::test_update_supports_complex_expression_attribute_values tests/test_dynamodb/test_dynamodb.py::test_update_expression_with_numeric_literal_instead_of_value tests/test_dynamodb/test_dynamodb.py::test_list_tables_boto3[multiple-tables] tests/test_dynamodb/test_dynamodb.py::test_update_list_index__set_nested_index_out_of_range tests/test_dynamodb/test_dynamodb.py::test_update_nested_item_if_original_value_is_none tests/test_dynamodb/test_dynamodb.py::test_update_supports_multiple_levels_nested_list_append tests/test_dynamodb/test_dynamodb.py::test_list_tables_boto3[one-table] tests/test_dynamodb/test_dynamodb.py::test_put_item_nonexisting_range_key tests/test_dynamodb/test_dynamodb.py::test_list_backups tests/test_dynamodb/test_dynamodb.py::test_query_filter_overlapping_expression_prefixes tests/test_dynamodb/test_dynamodb.py::test_source_and_restored_table_items_are_not_linked tests/test_dynamodb/test_dynamodb.py::test_bad_scan_filter tests/test_dynamodb/test_dynamodb.py::test_update_expression_with_minus_in_attribute_name tests/test_dynamodb/test_dynamodb.py::test_restore_table_from_backup_raises_error_when_table_already_exists tests/test_dynamodb/test_dynamodb.py::test_put_item_nonexisting_hash_key tests/test_dynamodb/test_dynamodb.py::test_restore_table_to_point_in_time_raises_error_when_source_not_exist tests/test_dynamodb/test_dynamodb.py::test_basic_projection_expression_using_get_item_with_attr_expression_names tests/test_dynamodb/test_dynamodb.py::test_invalid_transact_get_items tests/test_dynamodb/test_dynamodb.py::test_update_continuous_backups tests/test_dynamodb/test_dynamodb.py::test_update_item_atomic_counter tests/test_dynamodb/test_dynamodb.py::test_nested_projection_expression_using_query_with_attr_expression_names tests/test_dynamodb/test_dynamodb.py::test_item_add_empty_string_range_key_exception tests/test_dynamodb/test_dynamodb.py::test_get_item_for_non_existent_table_raises_error tests/test_dynamodb/test_dynamodb.py::test_scan_filter tests/test_dynamodb/test_dynamodb.py::test_error_when_providing_expression_and_nonexpression_params tests/test_dynamodb/test_dynamodb.py::test_update_return_attributes tests/test_dynamodb/test_dynamodb.py::test_item_size_is_under_400KB tests/test_dynamodb/test_dynamodb.py::test_multiple_updates tests/test_dynamodb/test_dynamodb.py::test_scan_filter4 tests/test_dynamodb/test_dynamodb.py::test_update_expression_with_space_in_attribute_name tests/test_dynamodb/test_dynamodb.py::test_create_multiple_backups_with_same_name tests/test_dynamodb/test_dynamodb.py::test_gsi_projection_type_keys_only tests/test_dynamodb/test_dynamodb.py::test_update_list_index__set_existing_nested_index tests/test_dynamodb/test_dynamodb.py::test_set_attribute_is_dropped_if_empty_after_update_expression[use tests/test_dynamodb/test_dynamodb.py::test_transact_write_items_put_conditional_expressions tests/test_dynamodb/test_dynamodb.py::test_restore_table_from_non_existent_backup_raises_error tests/test_dynamodb/test_dynamodb.py::test_query_by_non_exists_index tests/test_dynamodb/test_dynamodb.py::test_gsi_key_cannot_be_empty tests/test_dynamodb/test_dynamodb.py::test_remove_list_index__remove_index_out_of_range tests/test_dynamodb/test_dynamodb.py::test_transact_write_items_fails_with_transaction_canceled_exception tests/test_dynamodb/test_dynamodb.py::test_update_if_not_exists tests/test_dynamodb/test_dynamodb.py::test_remove_top_level_attribute tests/test_dynamodb/test_dynamodb.py::test_restore_table_from_backup tests/test_dynamodb/test_dynamodb.py::test_nested_projection_expression_using_scan_with_attr_expression_names tests/test_dynamodb/test_dynamodb.py::test_update_non_existing_item_raises_error_and_does_not_contain_item_afterwards tests/test_dynamodb/test_dynamodb.py::test_allow_update_to_item_with_different_type tests/test_dynamodb/test_dynamodb.py::test_describe_limits tests/test_dynamodb/test_dynamodb.py::test_sorted_query_with_numerical_sort_key tests/test_dynamodb/test_dynamodb.py::test_dynamodb_max_1mb_limit tests/test_dynamodb/test_dynamodb.py::test_update_continuous_backups_errors tests/test_dynamodb/test_dynamodb.py::test_list_backups_for_non_existent_table tests/test_dynamodb/test_dynamodb.py::test_duplicate_create tests/test_dynamodb/test_dynamodb.py::test_summing_up_2_strings_raises_exception tests/test_dynamodb/test_dynamodb.py::test_update_item_atomic_counter_return_values tests/test_dynamodb/test_dynamodb.py::test_put_item_with_special_chars tests/test_dynamodb/test_dynamodb.py::test_query_missing_expr_names tests/test_dynamodb/test_dynamodb.py::test_transact_write_items_update_with_failed_condition_expression tests/test_dynamodb/test_dynamodb.py::test_describe_endpoints[eu-central-1] tests/test_dynamodb/test_dynamodb.py::test_create_backup tests/test_dynamodb/test_dynamodb.py::test_query_filter tests/test_dynamodb/test_dynamodb.py::test_list_tables_boto3[no-table] tests/test_dynamodb/test_dynamodb.py::test_attribute_item_delete tests/test_dynamodb/test_dynamodb.py::test_invalid_projection_expressions tests/test_dynamodb/test_dynamodb.py::test_delete_item_error tests/test_dynamodb/test_dynamodb.py::test_update_list_index__set_existing_index tests/test_dynamodb/test_dynamodb.py::test_nested_projection_expression_using_get_item tests/test_dynamodb/test_dynamodb.py::test_nested_projection_expression_using_scan tests/test_dynamodb/test_dynamodb.py::test_update_item_on_map tests/test_dynamodb/test_dynamodb.py::test_restore_table_to_point_in_time tests/test_dynamodb/test_dynamodb.py::test_transact_write_items_put tests/test_dynamodb/test_dynamodb.py::test_basic_projection_expressions_using_query tests/test_dynamodb/test_dynamodb.py::test_list_not_found_table_tags tests/test_dynamodb/test_dynamodb.py::test_transact_write_items_update tests/test_dynamodb/test_dynamodb.py::test_update_return_updated_new_attributes_when_same tests/test_dynamodb/test_dynamodb.py::test_gsi_verify_negative_number_order tests/test_dynamodb/test_dynamodb.py::test_transact_write_items_conditioncheck_fails tests/test_dynamodb/test_dynamodb.py::test_set_ttl tests/test_dynamodb/test_dynamodb.py::test_scan_filter_should_not_return_non_existing_attributes tests/test_dynamodb/test_dynamodb.py::test_update_supports_list_append tests/test_dynamodb/test_dynamodb.py::test_put_return_attributes tests/test_dynamodb/test_dynamodb.py::test_lsi_projection_type_keys_only tests/test_dynamodb/test_dynamodb.py::test_remove_list_index__remove_multiple_indexes tests/test_dynamodb/test_dynamodb.py::test_update_list_index__set_double_nested_index tests/test_dynamodb/test_dynamodb.py::test_gsi_key_can_be_updated tests/test_dynamodb/test_dynamodb.py::test_put_item_with_streams tests/test_dynamodb/test_dynamodb.py::test_list_tables_exclusive_start_table_name_empty tests/test_dynamodb/test_dynamodb.py::test_update_item_with_no_action_passed_with_list tests/test_dynamodb/test_dynamodb.py::test_update_item_with_empty_string_attr_no_exception tests/test_dynamodb/test_dynamodb.py::test_transact_write_items_delete_with_failed_condition_expression tests/test_dynamodb/test_dynamodb.py::test_basic_projection_expressions_using_scan tests/test_dynamodb/test_dynamodb.py::test_list_table_tags tests/test_dynamodb/test_dynamodb.py::test_update_supports_nested_list_append_onto_another_list tests/test_dynamodb/test_dynamodb.py::test_update_list_index__set_index_out_of_range tests/test_dynamodb/test_dynamodb.py::test_filter_expression tests/test_dynamodb/test_dynamodb.py::test_basic_projection_expressions_using_scan_with_attr_expression_names tests/test_dynamodb/test_dynamodb.py::test_item_add_empty_string_hash_key_exception tests/test_dynamodb/test_dynamodb.py::test_item_add_empty_string_attr_no_exception tests/test_dynamodb/test_dynamodb.py::test_update_item_add_to_non_existent_set tests/test_dynamodb/test_dynamodb.py::test_gsi_projection_type_include tests/test_dynamodb/test_dynamodb.py::test_query_global_secondary_index_when_created_via_update_table_resource tests/test_dynamodb/test_dynamodb.py::test_update_item_add_to_non_existent_number_set tests/test_dynamodb/test_dynamodb.py::test_update_expression_with_multiple_set_clauses_must_be_comma_separated tests/test_dynamodb/test_dynamodb.py::test_scan_filter3 tests/test_dynamodb/test_dynamodb.py::test_update_list_index__set_index_of_a_string tests/test_dynamodb/test_dynamodb.py::test_update_supports_list_append_with_nested_if_not_exists_operation_and_property_already_exists tests/test_dynamodb/test_dynamodb.py::test_describe_endpoints[ap-south-1] tests/test_dynamodb/test_dynamodb.py::test_delete_table tests/test_dynamodb/test_dynamodb.py::test_update_item_add_to_list_using_legacy_attribute_updates tests/test_dynamodb/test_dynamodb.py::test_remove_top_level_attribute_non_existent tests/test_dynamodb/test_dynamodb.py::test_delete_non_existent_backup_raises_error tests/test_dynamodb/test_dynamodb.py::test_update_item_with_attribute_in_right_hand_side tests/test_dynamodb/test_dynamodb.py::test_list_table_tags_paginated