Skip to content

Commit

Permalink
Merge pull request #154 from kyleknap/merge-dicts-collections
Browse files Browse the repository at this point in the history
Fix filter method from clobering identifier params
  • Loading branch information
kyleknap committed Jun 29, 2015
2 parents 2d1842f + 7b86a82 commit 8318479
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 3 deletions.
6 changes: 3 additions & 3 deletions boto3/resources/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import logging

from botocore import xform_name
from botocore.utils import merge_dicts

from .action import BatchAction
from .params import create_request_parameters
Expand Down Expand Up @@ -106,7 +107,7 @@ def _clone(self, **kwargs):
:return: A clone of this resource collection
"""
params = copy.deepcopy(self._params)
params.update(kwargs)
merge_dicts(params, kwargs, append_lists=True)
clone = self.__class__(self._model, self._parent,
self._handler, **params)
return clone
Expand Down Expand Up @@ -135,10 +136,9 @@ def pages(self):
cleaned_params = self._params.copy()
limit = cleaned_params.pop('limit', None)
page_size = cleaned_params.pop('page_size', None)

params = create_request_parameters(
self._parent, self._model.request)
params.update(cleaned_params)
merge_dicts(params, cleaned_params, append_lists=True)

# Is this a paginated operation? If so, we need to get an
# iterator for the various pages. If not, then we simply
Expand Down
77 changes: 77 additions & 0 deletions tests/unit/resources/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,43 @@ def test_filters_paginated(self, handler):
PaginationConfig={'PageSize': None, 'MaxItems': 2},
Param1='foo', Param2=3)

@mock.patch('boto3.resources.collection.ResourceHandler')
def test_filter_does_not_clobber_existing_list_values(self, handler):
self.collection_def = {
'request': {
'operation': 'GetFrobs',
"params": [
{"target": "Filters[0].Name", "source": "string",
"value": "frob-id"},
{"target": "Filters[0].Values[0]", "source": "identifier",
"name": "Id"}
]
},
'resource': {
'type': 'Frob',
'identifiers': [
{'target': 'Id', 'source': 'response',
'path': 'Frobs[].Id'}
]
}
}
self.client.can_paginate.return_value = True
self.client.get_paginator.return_value.paginate.return_value = []
handler.return_value.return_value = []
collection = self.get_collection()

self.parent.id = 'my-id'
list(collection.filter(
Filters=[{'Name': 'another-filter', 'Values': ['foo']}]))
paginator = self.client.get_paginator.return_value
paginator.paginate.assert_called_with(
PaginationConfig={'PageSize': None, 'MaxItems': None},
Filters=[
{'Values': ['my-id'], 'Name': 'frob-id'},
{'Values': ['foo'], 'Name': 'another-filter'}
]
)

@mock.patch('boto3.resources.collection.ResourceHandler')
def test_page_size_param(self, handler):
self.client.can_paginate.return_value = True
Expand Down Expand Up @@ -553,6 +590,46 @@ def test_chaining_copies_parameters(self, handler):
paginator.paginate.assert_called_with(
PaginationConfig={'PageSize': 3, 'MaxItems': 3}, CustomArg=1)

@mock.patch('boto3.resources.collection.ResourceHandler')
def test_chaining_filters_does_not_clobber_list_values(self, handler):
self.collection_def = {
'request': {
'operation': 'GetFrobs',
"params": [
{"target": "Filters[0].Name", "source": "string",
"value": "frob-id"},
{"target": "Filters[0].Values[0]", "source": "identifier",
"name": "Id"}
]
},
'resource': {
'type': 'Frob',
'identifiers': [
{'target': 'Id', 'source': 'response',
'path': 'Frobs[].Id'}
]
}
}
self.client.can_paginate.return_value = True
self.client.get_paginator.return_value.paginate.return_value = []
handler.return_value.return_value = []
collection = self.get_collection()

self.parent.id = 'my-id'
collection = collection.filter(
Filters=[{'Name': 'second-filter', 'Values': ['foo']}])
list(collection.filter(
Filters=[{'Name': 'third-filter', 'Values': ['bar']}]))
paginator = self.client.get_paginator.return_value
paginator.paginate.assert_called_with(
PaginationConfig={'PageSize': None, 'MaxItems': None},
Filters=[
{'Values': ['my-id'], 'Name': 'frob-id'},
{'Values': ['foo'], 'Name': 'second-filter'},
{'Values': ['bar'], 'Name': 'third-filter'}
]
)

def test_chained_repr(self):
collection = self.get_collection()

Expand Down

0 comments on commit 8318479

Please sign in to comment.