Changes the storage for pagination information

fixes #232
This commit is contained in:
Aljoscha Rittner 2022-06-16 14:52:15 +02:00
pare e9d2c3d53f
commit 19dbb4594e
S'han modificat 3 arxius amb 37 adicions i 16 eliminacions

Veure arxiu

@ -120,10 +120,27 @@ class AttribAccessDict(dict):
raise AttributeError("Attribute-style access is read only") raise AttributeError("Attribute-style access is read only")
super(AttribAccessDict, self).__setattr__(attr, val) super(AttribAccessDict, self).__setattr__(attr, val)
###
# List helper class.
# Defined at top level so it can be pickled.
###
class AttribAccessList(list):
def __getattr__(self, attr):
if attr in self:
return self[attr]
else:
raise AttributeError("Attribute not found: " + str(attr))
def __setattr__(self, attr, val):
if attr in self:
raise AttributeError("Attribute-style access is read only")
super(AttribAccessList, self).__setattr__(attr, val)
### ###
# The actual Mastodon class # The actual Mastodon class
### ###
class Mastodon: class Mastodon:
""" """
Thorough and easy to use Mastodon Thorough and easy to use Mastodon
@ -3040,8 +3057,8 @@ class Mastodon:
Returns the next page or None if no further data is available. Returns the next page or None if no further data is available.
""" """
if isinstance(previous_page, list) and len(previous_page) != 0: if isinstance(previous_page, list) and len(previous_page) != 0:
if hasattr(previous_page[-1], '_pagination_next'): if hasattr(previous_page, '_pagination_next'):
params = copy.deepcopy(previous_page[-1]._pagination_next) params = copy.deepcopy(previous_page._pagination_next)
else: else:
return None return None
else: else:
@ -3064,8 +3081,8 @@ class Mastodon:
Returns the previous page or None if no further data is available. Returns the previous page or None if no further data is available.
""" """
if isinstance(next_page, list) and len(next_page) != 0: if isinstance(next_page, list) and len(next_page) != 0:
if hasattr(next_page[0], '_pagination_prev'): if hasattr(next_page, '_pagination_prev'):
params = copy.deepcopy(next_page[0]._pagination_prev) params = copy.deepcopy(next_page._pagination_prev)
else: else:
return None return None
else: else:
@ -3443,6 +3460,7 @@ class Mastodon:
if isinstance(response, list) and \ if isinstance(response, list) and \
'Link' in response_object.headers and \ 'Link' in response_object.headers and \
response_object.headers['Link'] != "": response_object.headers['Link'] != "":
response = AttribAccessList(response)
tmp_urls = requests.utils.parse_header_links( tmp_urls = requests.utils.parse_header_links(
response_object.headers['Link'].rstrip('>').replace('>,<', ',<')) response_object.headers['Link'].rstrip('>').replace('>,<', ',<'))
for url in tmp_urls: for url in tmp_urls:
@ -3467,7 +3485,7 @@ class Mastodon:
del next_params['since_id'] del next_params['since_id']
if "min_id" in next_params: if "min_id" in next_params:
del next_params['min_id'] del next_params['min_id']
response[-1]._pagination_next = next_params response._pagination_next = next_params
if url['rel'] == 'prev': if url['rel'] == 'prev':
# Be paranoid and extract since_id or min_id specifically # Be paranoid and extract since_id or min_id specifically
@ -3486,7 +3504,7 @@ class Mastodon:
prev_params['since_id'] = since_id prev_params['since_id'] = since_id
if "max_id" in prev_params: if "max_id" in prev_params:
del prev_params['max_id'] del prev_params['max_id']
response[0]._pagination_prev = prev_params response._pagination_prev = prev_params
# New and fantastico (post-2.6.0): min_id pagination # New and fantastico (post-2.6.0): min_id pagination
matchgroups = re.search(r"[?&]min_id=([^&]+)", prev_url) matchgroups = re.search(r"[?&]min_id=([^&]+)", prev_url)
@ -3501,7 +3519,7 @@ class Mastodon:
prev_params['min_id'] = min_id prev_params['min_id'] = min_id
if "max_id" in prev_params: if "max_id" in prev_params:
del prev_params['max_id'] del prev_params['max_id']
response[0]._pagination_prev = prev_params response._pagination_prev = prev_params
return response return response

Veure arxiu

@ -10,10 +10,13 @@ interactions:
method: GET method: GET
uri: http://localhost:3000/api/v1/domain_blocks uri: http://localhost:3000/api/v1/domain_blocks
response: response:
body: {string: '[]'} body: {string: '["example.com"]'}
headers: headers:
Cache-Control: ['no-cache, no-store'] Cache-Control: ['no-cache, no-store']
Content-Type: [application/json; charset=utf-8] Content-Type: [application/json; charset=utf-8]
Link: ['<http://localhost:3000/api/v1/domain_blocks?max_id=10023>;
rel="next", <http://localhost:3000/api/v1/domain_blocks?min_id=10021>;
rel="prev"']
Referrer-Policy: [strict-origin-when-cross-origin] Referrer-Policy: [strict-origin-when-cross-origin]
Transfer-Encoding: [chunked] Transfer-Encoding: [chunked]
Vary: ['Accept-Encoding, Origin'] Vary: ['Accept-Encoding, Origin']
@ -24,6 +27,6 @@ interactions:
X-Request-Id: [79ec8c37-a374-47e4-a698-a8b8511ca20f] X-Request-Id: [79ec8c37-a374-47e4-a698-a8b8511ca20f]
X-Runtime: ['0.098492'] X-Runtime: ['0.098492']
X-XSS-Protection: [1; mode=block] X-XSS-Protection: [1; mode=block]
content-length: ['2'] content-length: ['15']
status: {code: 200, message: OK} status: {code: 200, message: OK}
version: 1 version: 1

Veure arxiu

@ -39,9 +39,9 @@ def test_fetch_next_previous_from_pagination_info(api):
account = api.account_verify_credentials() account = api.account_verify_credentials()
with many_statuses(api): with many_statuses(api):
statuses = api.account_statuses(account['id'], limit=5) statuses = api.account_statuses(account['id'], limit=5)
next_statuses = api.fetch_next(statuses[-1]._pagination_next) next_statuses = api.fetch_next(statuses._pagination_next)
assert next_statuses assert next_statuses
previous_statuses = api.fetch_previous(next_statuses[0]._pagination_prev) previous_statuses = api.fetch_previous(next_statuses._pagination_prev)
assert previous_statuses assert previous_statuses
def test_fetch_next_previous_old_pagination(api): def test_fetch_next_previous_old_pagination(api):
@ -61,9 +61,9 @@ def test_fetch_next_previous_from_pagination_info_old_pagination(api):
with many_statuses(api): with many_statuses(api):
statuses = api.account_statuses(account['id'], limit=5) statuses = api.account_statuses(account['id'], limit=5)
next_statuses = api.fetch_next(statuses[-1]._pagination_next) next_statuses = api.fetch_next(statuses._pagination_next)
assert next_statuses assert next_statuses
previous_statuses = api.fetch_previous(next_statuses[0]._pagination_prev) previous_statuses = api.fetch_previous(next_statuses._pagination_prev)
assert previous_statuses assert previous_statuses
@pytest.mark.vcr() @pytest.mark.vcr()
@ -86,5 +86,5 @@ def test_link_headers(api):
}) })
resp = api.timeline_hashtag(UNLIKELY_HASHTAG) resp = api.timeline_hashtag(UNLIKELY_HASHTAG)
assert resp[0]._pagination_next['max_id'] == _id assert resp._pagination_next['max_id'] == _id
assert resp[0]._pagination_prev['since_id'] == _id assert resp._pagination_prev['since_id'] == _id