Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make users.incremental() work like tickets.incremental() #576

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 68 additions & 65 deletions zenpy/lib/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,71 @@ def incremental(self, start_time, include=None, per_page=None):
per_page=per_page)


class IncrementalCursorApi(IncrementalApi):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice lift

def incremental(self,
start_time=None,
paginate_by_time=True,
cursor=None,
include=None,
per_page=None):
"""
Incrementally retrieve Tickets or Users.

If paginate_by_time is True, a ZendeskResultGenerator is returned to handle
time based pagination. This is defaulted to True for backwards compatibility
but is not recommended by Zendesk.

If paginate_by_time is False, a TicketCursorGenerator or a UserCursorGenerator is returned to handle
cursor based pagination. This is recommended by Zendesk.

This allows you to change the direction that you are consuming objects.
This is done with the reversed() python method.

For example:

.. code-block:: python

for ticket in reversed(zenpy_client.tickets.incremental(cursor='xxx')):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perpetuated badness :)

print(ticket)

See the `Zendesk docs <https://developer.zendesk.com/rest_api/docs/support/incremental_export#cursor-based-incremental-exports>`__ for
information on additional parameters.

:param start_time: the time of the oldest object you are interested in, applies to both time/cursor based pagination.
:param paginate_by_time: True to use time based pagination, False to use cursor based pagination.
:param cursor: cursor value of the page you are interested in, can't be set with start_time.
:param include: list of objects to sideload. `Side-loading API Docs
<https://developer.zendesk.com/rest_api/docs/core/side_loading>`__.
:param per_page: number of results per page, up to max 1000
"""
if (all_are_none(start_time, cursor)
or all_are_not_none(start_time, cursor)):
raise ValueError(
'You must set either start_time or cursor but not both')

if start_time and paginate_by_time is True:
return super(IncrementalCursorApi, self).incremental(start_time=start_time,
include=include,
per_page=per_page)

elif start_time and paginate_by_time is False:
return self._query_zendesk(self.endpoint.incremental.cursor_start,
self.object_type,
start_time=start_time,
include=include,
per_page=per_page)

elif cursor and paginate_by_time is False:
return self._query_zendesk(self.endpoint.incremental.cursor,
self.object_type,
cursor=cursor,
include=include,
per_page=per_page)
else:
raise ValueError(
"Can't set cursor param and paginate_by_time=True")


class ChatIncrementalApi(Api):
"""
ChatIncrementalApi supports the chat incremental endpoint.
Expand Down Expand Up @@ -855,7 +920,7 @@ def __call__(self, query=None, external_id=None):
return self._get(url, params=params)


class UserApi(IncrementalApi, CRUDExternalApi, TaggableApi):
class UserApi(IncrementalCursorApi, CRUDExternalApi, TaggableApi):
"""
The UserApi adds some User specific functionality
"""
Expand All @@ -865,6 +930,7 @@ def __init__(self, config):
self.identities = UserIdentityApi(config)
self.search = UserSearchApi(config)


@extract_id(User)
def groups(self, user, include=None):
"""
Expand Down Expand Up @@ -1284,7 +1350,7 @@ def apply(self, macro):
return self._query_zendesk(self.endpoint.apply, 'result', id=macro)


class TicketApi(RateableApi, TaggableApi, IncrementalApi, CRUDApi):
class TicketApi(RateableApi, TaggableApi, IncrementalCursorApi, CRUDApi):
"""
The TicketApi adds some Ticket specific functionality
"""
Expand Down Expand Up @@ -1515,69 +1581,6 @@ def skips(self, ticket):

return self._get(self._build_url(self.endpoint.skips(id=ticket)))

def incremental(self,
start_time=None,
paginate_by_time=True,
cursor=None,
include=None,
per_page=None):
"""
Incrementally retrieve Tickets.

If paginate_by_time is True, a ZendeskResultGenerator is returned to handle
time based pagination. This is defaulted to True for backwards compatibility
but is not recommended by Zendesk.

If paginate_by_time is False, a TicketCursorGenerator is returned to handle
cursor based pagination. This is recommended by Zendesk.

The TicketCursorGenerator allows you to change the direction that you are consuming objects.
This is done with the reversed() python method.

For example:

.. code-block:: python

for ticket in reversed(zenpy_client.tickets.incremental(cursor='xxx')):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you did not write this, but this example face plants :)

for ticket in zenpy_client.tickets.incremental(cursor="MTY4NDYzNDU0Mi4wfHw2fA=="):
	print(ticket)
jteitelbaum@Q7T6X1LF2M pythontests % python3 incremental_users_test.py                     
Traceback (most recent call last):
  File "/Users/jteitelbaum/Code/pythontests/incremental_users_test.py", line 29, in <module>
    for ticket in zenpy_client.tickets.incremental(cursor="MTY4NDYzNDU0Mi4wfHw2fA=="):
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jteitelbaum/Code/zenpy/zenpy/lib/api.py", line 770, in incremental
    raise ValueError(
ValueError: Can't set cursor param and paginate_by_time=True

print(ticket)

See the `Zendesk docs <https://developer.zendesk.com/rest_api/docs/support/incremental_export#cursor-based-incremental-exports>`__ for
information on additional parameters.

:param start_time: the time of the oldest object you are interested in, applies to both time/cursor based pagination.
:param paginate_by_time: True to use time based pagination, False to use cursor based pagination.
:param cursor: cursor value of the page you are interested in, can't be set with start_time.
:param include: list of objects to sideload. `Side-loading API Docs
<https://developer.zendesk.com/rest_api/docs/core/side_loading>`__.
:param per_page: number of results per page, up to max 1000
"""
if (all_are_none(start_time, cursor)
or all_are_not_none(start_time, cursor)):
raise ValueError(
'You must set either start_time or cursor but not both')

if start_time and paginate_by_time is True:
return super(TicketApi, self).incremental(start_time=start_time,
include=include,
per_page=per_page)

elif start_time and paginate_by_time is False:
return self._query_zendesk(self.endpoint.incremental.cursor_start,
self.object_type,
start_time=start_time,
include=include,
per_page=per_page)

elif cursor and paginate_by_time is False:
return self._query_zendesk(self.endpoint.incremental.cursor,
self.object_type,
cursor=cursor,
include=include,
per_page=per_page)
else:
raise ValueError(
"Can't set cursor param and paginate_by_time=True")


class SkipApi(CRUDApi):
def __init__(self, config):
Expand Down
2 changes: 2 additions & 0 deletions zenpy/lib/endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,8 @@ class EndpointFactory(object):
users.deleted = PrimaryEndpoint("deleted_users")
users.groups = SecondaryEndpoint('users/%(id)s/groups.json')
users.incremental = IncrementalEndpoint('incremental/users.json')
users.incremental.cursor_start = IncrementalEndpoint(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm yes seems parity was not here :)

'incremental/users/cursor.json')
users.me = PrimaryEndpoint('users/me')
users.merge = SecondaryEndpoint('users/%(id)s/merge.json')
users.votes = SecondaryEndpoint(
Expand Down