Skip to content

Commit

Permalink
Issue #595 fixes search export CBP (#629)
Browse files Browse the repository at this point in the history
* Issue #595 fixes search export CBP

* Added changelog
  • Loading branch information
cryptomail committed May 13, 2024
1 parent 438902e commit 593ccf9
Show file tree
Hide file tree
Showing 8 changed files with 510 additions and 14 deletions.
8 changes: 0 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@ run_linter: &run_linter
version: 2
jobs:
python3.5:
docker:
- image: cimg/python:3.5
working_director: ~/repo
steps:
- checkout
- <<: *run_tests
python3.6:
docker:
- image: cimg/python:3.6
Expand Down Expand Up @@ -80,7 +73,6 @@ workflows:
build_and_test:
jobs:
- linter
- python3.5
- python3.6
- python3.7
- python3.8
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## [2.0.49] - 2024-05-13

### Added
- This file ^_^

### Fixed
- Fixed issue https://github.com/facetoe/zenpy/issues/595

### Changed
- None

### Removed
- Dropped support for Python 3.5

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
{
"http_interactions": [
{
"recorded_at": "2024-05-13T15:23:40",
"request": {
"body": {
"encoding": "utf-8",
"string": ""
},
"headers": {
"Accept": [
"*/*"
],
"Accept-Encoding": [
"gzip, deflate"
],
"Authorization": [
"Basic <ZENPY-CREDENTIALS>"
],
"Connection": [
"keep-alive"
],
"Cookie": [
"_zendesk_cookie=BAhJIhl7ImRldmljZV90b2tlbnMiOnt9fQY6BkVU--475022cc997e69578b2d9a10ef8a78a673ab36a3"
],
"User-Agent": [
"Zenpy/2.0.48"
]
},
"method": "GET",
"uri": "https://z3n-sell-mrhandy-699517ac91.zendesk-staging.com/api/v2/search/export.json?page%5Bsize%5D=1&query=created_at%3E%3D2023-09-14T00%3A39%3A54Z%20type%3Auser&filter%5Btype%5D=user"
},
"response": {
"body": {
"base64_string": "H4sIAAAAAAAAA+1VXY+bOBT9KyOk9KXJhECYTiJVu+kk02ZUGDUlyQyrFXKMA06MobZJCKP573tNCZN96kP3cSWE8PW5X+dcmxdDEFkwJY3xXy8GjYzxB+d25JhD2xneDuyuUQhmjI1EqVyO+/3K5j1JGOulIkE8OvVuRiNn8AHh0eC6Ijwict+TCsWUx9c4S/sop/2D1S8kEbL/r8jXO5lxo2twlBJIsGEoudIvMJEUUZ0UksHzJ8TVBh0PNrEgSJEoRAoQlmnZPXPUG9z6ljm2b8bmMABMkUe/xCiakrDKuE4+54oIjhTNOGJXU/C9+ko5uVoTqQBKEUfhJX6mcP+z678fWLCbJ7WRF4x1DZkgAYlrW8iLdEPEeQtsKjsvWIYRI6Hme3BeQWDCe8vvEDMTMeK0qiuqQT+9RNagop5mFIAHIuiWEkBsEZMEuCvrVtiFF8ih1f27ayBGEXwa4IiwogcIpkRBzmW3QZouUEy4ao0MSRWyDKSteW1iH7NwC7EyEaJCJSHhaMNIm1rSGGgtRMtPRBRI2dTAM0WaT91ZqE55C8SFVFka1va3VtIsIgJBtrYqRfGeqBCGWAmKNV8QUJAfBRigDqCSs1OYC3oAVUMYoRR6kq372e+t24aQQuZ6nN84icgWwTkJY5EV+aUmJM+ECrE8tFCtTQiqsAgSvRgRkvpDw1+7zXFreq2hxitIAyQSJds+gSbtmiAZpplodUJbUDfEhZCaAoOcHlK0Xsngbn4zT71TsL43g/Vi+/z0jX69e9gHT95uvstNzFcM1iZg73C6SpAZ5MG63M93GUXrGnuxt2DYculjGiSbL572qzb2g7lK72W0XlUQb+P6z47nT6xH37W86eTo3h1tz4+1zXSrpfk4nVVP3480eEqO2hdqWqIvq2qR3p8gZ6ljQm0VWo+Kpb1IMP9GH3cz2/WXluu7Q3c3GXr+Xl709CmCHl0fl57/XLpVfHKnse1BDmxBXZ9X+2W6KnV90SxJsBVDvDng9iX4ON4ulnPuQT8LFsy8AebeAe8bHDVL2LeAKcebLkYwMhuyBc5bmhvhGOX7Ws9ckMNZKA7n7fevR0mQwEmflHqU6ovxjy1lIHXH+aQHpeNMP+pJeZfDkIKtHgNt/H8A/vsBOJMsaVUTP3gHl4k4fXz78XTsWceetv+VoW+aHXtij+DlDIP3tWL25OfRfv0HpN5HNGEHAAA=",
"encoding": "utf-8",
"string": ""
},
"headers": {
"Connection": [
"keep-alive"
],
"Content-Encoding": [
"gzip"
],
"Content-Type": [
"application/json; charset=utf-8"
],
"Date": [
"Mon, 13 May 2024 15:23:40 GMT"
],
"Server": [
"openresty"
],
"Transfer-Encoding": [
"chunked"
],
"X-Request-ID": [
"f051b7c7f1ea9a2d1e897baf73f622a5"
],
"X-Zendesk-API-Gateway": [
"yes"
],
"X-Zendesk-Zorg": [
"yes"
],
"cache-control": [
"max-age=10, private"
],
"etag": [
"W/\"1f319f0ca7be300ae607c81a49954579\""
],
"ratelimit-limit": [
"700"
],
"ratelimit-remaining": [
"697"
],
"ratelimit-reset": [
"20"
],
"strict-transport-security": [
"max-age=31536000; includeSubDomains"
],
"x-frame-options": [
"SAMEORIGIN"
],
"x-rate-limit": [
"700"
],
"x-rate-limit-remaining": [
"697"
],
"x-runtime": [
"0.141746"
],
"x-zendesk-api-version": [
"v2"
],
"x-zendesk-application-version": [
"v20879"
],
"x-zendesk-origin-server": [
"classic-app-server-7f84944b94-bbhkg"
]
},
"status": {
"code": 200,
"message": "OK"
},
"url": "https://z3n-sell-mrhandy-699517ac91.zendesk-staging.com/api/v2/search/export.json?page%5Bsize%5D=1&query=created_at%3E%3D2023-09-14T00%3A39%3A54Z%20type%3Auser&filter%5Btype%5D=user"
}
},
{
"recorded_at": "2024-05-13T15:23:41",
"request": {
"body": {
"encoding": "utf-8",
"string": ""
},
"headers": {
"Accept": [
"*/*"
],
"Accept-Encoding": [
"gzip, deflate"
],
"Authorization": [
"Basic <ZENPY-CREDENTIALS>"
],
"Connection": [
"keep-alive"
],
"Cookie": [
"_zendesk_cookie=BAhJIhl7ImRldmljZV90b2tlbnMiOnt9fQY6BkVU--475022cc997e69578b2d9a10ef8a78a673ab36a3"
],
"User-Agent": [
"Zenpy/2.0.48"
]
},
"method": "GET",
"uri": "https://z3n-sell-mrhandy-699517ac91.zendesk-staging.com/api/v2/search/export.json?filter%5Btype%5D=user&page%5Bafter%5D=eyJmaWVsZCI6ImNyZWF0ZWRfYXQiLCJkZXNjIjp0cnVlLCJ0aWVCcmVha0ZpZWxkIjoiaWQiLCJ0aWVCcmVha0Rlc2MiOmZhbHNlLCJzb3J0VmFsdWVzIjpbMTY5NTA2OTM2NDAwMCw3NTg5NTA0MzU0ODEzXSwiZXhwb3J0ZWRUaHVzRmFyIjoxLCJzZXNzaW9uU3RhcnQiOjE3MTU2MTM4MjA4NTksImNyZWF0ZWRBdCI6MTcxNTYxMzgyMDg3NSwic2FsdGVkUmVxdWVzdEhhc2giOjIxMzkxMTc5NjgsInNhbHRlZEN1cnNvckhhc2giOi0xNjg2NjI5NDR9&page%5Bsize%5D=1&query=created_at%3E%3D2023-09-14T00%3A39%3A54Z+type%3Auser"
},
"response": {
"body": {
"base64_string": "H4sIAAAAAAAAA+1VXW/iOBT9K1Uk5mWg5IO0gFTNMi2doZoElQnQZrWKTGISg+NkbAdIqv73vXaBdp5X87YIofh+33OOw4vBsaioFMbw7xeDJMbw2u0PXLNn24N+320bFafG0MikLMWw220c1hGY0k7OM8SSunM1GLjWNYoH1mWDWYLFtiMkSglLL+Mi76KSdHd2txKYi+5vlS83omBG22Aox9Ag4CTe1heE7YoYSaJdOEdENV8Tnv8FndVRVQVXzDGSOImQBL9t2k7HHHSsfmCbQ8cdOk4IMVWZ/BbT65hOxx4Etj20r4eujpEkx1FTMDXChEnMmW6O6MUd5F78IAxfLLGQEEoQQ9HH+LGMu9+84LNlg7fMtJFVlLYNkSEOjbUtYlW+wvzkApssTgcKu1IcKdSt0wkKY9aZ/4SaBU8RI42eSAe9ZfFCR6EUMzXXDnOyJhjca0QFBtgOeg/6IQUYUQT/0zYQJQgeDUhEsSQ7qCR5hU8zn4scV3hrcjJSJGREC2BXg3qsvS+iNdQqeIQqmUWYoRXF59aCpIBpxfFb0wRLYPE4ASskPj6qpSJZlxBmAr2VkEUeaaNGxzLV58q0XafXNvIiwRxBx/NkEtSDZQRaliAkrZ+hkfKiKoUCktE6KjnZAacRCCiHpcQ595T0vu4RkUqUStLvoCR4jeCuRLqwHuza7luOdTXoO33TVaXKgssoFrtzjpJ+BPzQBDq+GAkS6kFh89o+3r3j3jrUeAWSAE4sxQnBHCBTqRkSUV7wM2NoDTxHccWFAsLA9UOOlgsR3k6uJrlfh8t7M1zO1s9Pj+TH7cM2fPI3k01pxmxB4WxC7G2cLzJkhmW4PGwnm4KgpY794JvR2PbINA+z1Xdf5TUr58Fc5PciWS4aqLfygmfXD0b2NPAarxntvdu94wepspneZuJO71Lr6eeehE/ZXuXCTHP0fdHM8vsaetaqJszWoOWgmjuzLGaPZLoZO14wt73A63mbUc8PtuLDTl8T2NEL4oMfPB+8Jq096A99SWzDXN8W23m+OKj5knGWxXYK9SYQtz1AjutvUjFhPuwzo+HYt2Lm7+LtMY6YB3/j1d7GM6fBc2/9eHMD+lnhNeB+hvpIHiVsqzktOd6dyGJw+/77+1JgxOOsiw9KTvpN+WVNKNDdcr8qsbTcuxullk8lKBZsWgrK+L8I/oQIWs4dfE9gC9JoAqxPvyrM65v3/6KWM4a4899RLzDNljNyBvDj9sLPmjln9HbNX/8FnXLr93oHAAA=",
"encoding": "utf-8",
"string": ""
},
"headers": {
"Connection": [
"keep-alive"
],
"Content-Encoding": [
"gzip"
],
"Content-Type": [
"application/json; charset=utf-8"
],
"Date": [
"Mon, 13 May 2024 15:23:41 GMT"
],
"Server": [
"openresty"
],
"Transfer-Encoding": [
"chunked"
],
"X-Request-ID": [
"aab04b38f490536c649f5fed92e31769"
],
"X-Zendesk-API-Gateway": [
"yes"
],
"X-Zendesk-Zorg": [
"yes"
],
"cache-control": [
"max-age=10, private"
],
"etag": [
"W/\"be75313ba286a2be9a76c85b62532141\""
],
"ratelimit-limit": [
"700"
],
"ratelimit-remaining": [
"696"
],
"ratelimit-reset": [
"19"
],
"strict-transport-security": [
"max-age=31536000; includeSubDomains"
],
"x-frame-options": [
"SAMEORIGIN"
],
"x-rate-limit": [
"700"
],
"x-rate-limit-remaining": [
"696"
],
"x-runtime": [
"0.153174"
],
"x-zendesk-api-version": [
"v2"
],
"x-zendesk-application-version": [
"v20879"
],
"x-zendesk-origin-server": [
"classic-app-server-7f84944b94-6zpkc"
]
},
"status": {
"code": 200,
"message": "OK"
},
"url": "https://z3n-sell-mrhandy-699517ac91.zendesk-staging.com/api/v2/search/export.json?filter%5Btype%5D=user&page%5Bafter%5D=eyJmaWVsZCI6ImNyZWF0ZWRfYXQiLCJkZXNjIjp0cnVlLCJ0aWVCcmVha0ZpZWxkIjoiaWQiLCJ0aWVCcmVha0Rlc2MiOmZhbHNlLCJzb3J0VmFsdWVzIjpbMTY5NTA2OTM2NDAwMCw3NTg5NTA0MzU0ODEzXSwiZXhwb3J0ZWRUaHVzRmFyIjoxLCJzZXNzaW9uU3RhcnQiOjE3MTU2MTM4MjA4NTksImNyZWF0ZWRBdCI6MTcxNTYxMzgyMDg3NSwic2FsdGVkUmVxdWVzdEhhc2giOjIxMzkxMTc5NjgsInNhbHRlZEN1cnNvckhhc2giOi0xNjg2NjI5NDR9&page%5Bsize%5D=1&query=created_at%3E%3D2023-09-14T00%3A39%3A54Z+type%3Auser"
}
}
],
"recorded_with": "betamax/0.8.1"
}
31 changes: 31 additions & 0 deletions tests/test_api/test_user_search_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,34 @@ def test_raises_zenpyexception_when_neither_query_nor_external_id_are_set(self):
def test_raises_zenpyexception_when_both_query_and_external_id_are_set(self):
with self.assertRaises(ZenpyException):
self.zenpy_client.users.search(query=1, external_id=2)


class TestUserSearchExportApi(ZenpyApiTestCase):
__test__ = True
def test_cbp_small_iterations(self):
cassette_name = "{}".format(self.generate_cassette_name())
with self.recorder.use_cassette(
cassette_name=cassette_name, serialize_with="prettyjson"
):
created_at = "2023-09-14T00:39:54Z"
count = 0
users = self.zenpy_client.search_export(query=f"created_at>={created_at}", type="user", cursor_pagination=1)
for _ in users:
count = count + 1
if count >= 2:
break
self.assertGreater(count, 1, "Default pagination returned less than 2 objects")

def test_cbp_large_block(self):
cassette_name = "{}".format(self.generate_cassette_name())
with self.recorder.use_cassette(
cassette_name=cassette_name, serialize_with="prettyjson"
):
created_at = "2019-09-14T00:39:54Z"
count = 0
users = self.zenpy_client.search_export(query=f"created_at>={created_at}", type="user", cursor_pagination=1000)
for _ in users:
count = count + 1
if count >= 1001:
break
self.assertGreater(count, 1000, "Default pagination returned less than 1001 objects")
1 change: 1 addition & 0 deletions zenpy/lib/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ def supports_cbp(self):
'organizations',
'organization_memberships',
'recipient_addresses',
'search/export.json',
'satisfaction_ratings',
'skips',
'suspended_tickets',
Expand Down
15 changes: 10 additions & 5 deletions zenpy/lib/endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,12 +314,16 @@ class SearchEndpoint(BaseEndpoint):
"""
def __call__(self, query=None, **kwargs):

renamed_kwargs = dict()
modifiers = list()
params = dict()
for key, value in kwargs.items():
if isinstance(value, datetime):
if key == 'cursor_pagination':
if value is True:
params['page[size]'] = 100
elif value is not False:
params['page[size]'] = value
elif isinstance(value, datetime):
kwargs[key] = value.strftime(self.ISO_8601_FORMAT)
elif isinstance(value, date):
kwargs[key] = value.strftime(self.ZENDESK_DATE_FORMAT)
Expand Down Expand Up @@ -353,9 +357,10 @@ def __call__(self, query=None, **kwargs):
elif is_iterable_but_not_string(value):
modifiers.append(self.format_or(key, value))
else:
if isinstance(value, str) and value.count(' ') > 0:
value = '"{}"'.format(value)
renamed_kwargs.update({key + ':': '%s' % value})
if (key != 'cursor_pagination'):
if isinstance(value, str) and value.count(' ') > 0:
value = '"{}"'.format(value)
renamed_kwargs.update({key + ':': '%s' % value})

search_query = [
'%s%s' % (key, value) for (key, value) in renamed_kwargs.items()
Expand Down
2 changes: 1 addition & 1 deletion zenpy/lib/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def next(self):
self.values = self.process_page()
if self.position >= len(self.values):
self.handle_pagination()
if len(self.values) < 1:
if len(self.values) < 1 or self.position >= len(self.values):
raise StopIteration()
zenpy_object = self.values[self.position]
self.position += 1
Expand Down

0 comments on commit 593ccf9

Please sign in to comment.