Part of structured approach for UpdateExpressions:
1) Expression gets parsed into a tokenlist (tokenized)
2) Tokenlist get transformed to expression tree (AST)
3) The AST gets validated (full semantic correctness)
4) AST gets processed to perform the update -> this commit
This commit uses the AST to execute the UpdateExpression.
All the existing tests pass. The only tests that have been
updated are in test_dynamodb_table_with_range_key.py because
they wrongly allow adding a set to a path that doesn't exist.
This has been alligend to correspond to the behavior of AWS
DynamoDB.
This commit will resolve https://github.com/spulec/moto/issues/2806
Multiple tests have been implemented that verify this.
The new version of botcore adds this region: f7dc4730ad (diff-9dfab05d4ba739e097a193e8b5fa61caR13)
Which in turn, breaks moto:
```
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/__init__.py:3: in <module>
from .acm import mock_acm # noqa
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/acm/__init__.py:2: in <module>
from .models import acm_backends
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/acm/models.py:7: in <module>
from moto.ec2 import ec2_backends
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/__init__.py:2: in <module>
from .models import ec2_backends
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:5169: in <module>
ec2_backends = {
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:5170: in <dictcomp>
region.name: EC2Backend(region.name) for region in RegionsAndZonesBackend.regions
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:5083: in __init__
super(EC2Backend, self).__init__()
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:852: in __init__
super(InstanceBackend, self).__init__()
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:1127: in __init__
super(TagBackend, self).__init__()
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:2368: in __init__
super(EBSBackend, self).__init__()
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:1904: in __init__
super(SecurityGroupBackend, self).__init__()
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:1355: in __init__
self._load_amis()
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:1362: in _load_amis
self.amis[ami_id] = Ami(self, **ami)
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:1313: in __init__
volume = self.ec2_backend.create_volume(15, region_name)
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:2372: in create_volume
zone = self.get_zone_by_name(zone_name)
/moto-1.3.15.dev640-py2.py3-none-any.whl/moto/ec2/models.py:1713: in get_zone_by_name
for zone in self.zones[self.region_name]:
E KeyError: 'af-south-1'
```
The "request" object in CallbackResponse is the PreparedRequest send by
whatever client is used to contact the mocked moto service. This can end
up with unparsed bodies, as we added for processing presigned post
requests in #2155. This will make sure that all of the requests comming
in from mocked functions also get processed by werkzeug as if it was
running a live server.