'Set the start and end of this query using serialized cursors.
Conceptually cursors point to the position between the last result returned
and the next result so running a query with each of the following cursors
combinations will return all results in four chunks with no duplicate
results:
query.with_cursor(end_cursor=cursor1)
query.with_cursors(cursor1, cursor2)
query.with_cursors(cursor2, cursor3)
query.with_cursors(start_cursor=cursor3)
For example if the cursors pointed to:
cursor:    1   2   3
result: a b c d e f g h
The results returned by these queries would be [a, b], [c, d], [e, f],
[g, h] respectively.
Cursors are pinned to the position just after the previous result (last
result, exclusive), so if results are inserted or deleted between the time
the cursor was made and these queries are executed, the cursors stay pinned
to these positions. For example:
delete(b, f, g, h)
put(a1, b1, c1, d1)
cursor:     1(b)      2(d)   3(f)
result: a a1 b1 c c1 d d1 e
The results returned by these queries would now be: [a, a1], [b1, c, c1, d],
[d1, e], [] respectively.
Args:
start_cursor: The cursor position at which to start or None
end_cursor: The cursor position at which to end or None
Returns:
This Query instance, for chaining.
Raises:
BadValueError when cursor is not valid.'

def with_cursor(self, start_cursor=None, end_cursor=None):

    if (start_cursor is None):
        self._cursor = None
    else:
        self._cursor = websafe_decode_cursor(start_cursor)
    if (end_cursor is None):
        self._end_cursor = None
    else:
        self._end_cursor = websafe_decode_cursor(end_cursor)
    return self
