diff options
-rw-r--r-- | Pipfile | 1 | ||||
-rw-r--r-- | Pipfile.lock | 8 | ||||
-rw-r--r-- | mastodon/Mastodon.py | 16 | ||||
-rw-r--r-- | setup.py | 2 | ||||
-rw-r--r-- | tests/test_pagination.py | 20 |
5 files changed, 42 insertions, 5 deletions
@@ -13,3 +13,4 @@ pytest-cov = "*" | |||
13 | vcrpy = "*" | 13 | vcrpy = "*" |
14 | pytest-vcr = "<1" | 14 | pytest-vcr = "<1" |
15 | pytest-mock = "*" | 15 | pytest-mock = "*" |
16 | requests-mock = "*" | ||
diff --git a/Pipfile.lock b/Pipfile.lock index d1939fc..db1193b 100644 --- a/Pipfile.lock +++ b/Pipfile.lock | |||
@@ -313,6 +313,14 @@ | |||
313 | ], | 313 | ], |
314 | "version": "==2.20.1" | 314 | "version": "==2.20.1" |
315 | }, | 315 | }, |
316 | "requests-mock": { | ||
317 | "hashes": [ | ||
318 | "sha256:7a5fa99db5e3a2a961b6f20ed40ee6baeff73503cf0a553cc4d679409e6170fb", | ||
319 | "sha256:8ca0628dc66d3f212878932fd741b02aa197ad53fd2228164800a169a4a826af" | ||
320 | ], | ||
321 | "index": "pypi", | ||
322 | "version": "==1.5.2" | ||
323 | }, | ||
316 | "six": { | 324 | "six": { |
317 | "hashes": [ | 325 | "hashes": [ |
318 | "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", | 326 | "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", |
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py index 37e35b7..98cebab 100644 --- a/mastodon/Mastodon.py +++ b/mastodon/Mastodon.py | |||
@@ -2275,13 +2275,17 @@ class Mastodon: | |||
2275 | if url['rel'] == 'next': | 2275 | if url['rel'] == 'next': |
2276 | # Be paranoid and extract max_id specifically | 2276 | # Be paranoid and extract max_id specifically |
2277 | next_url = url['url'] | 2277 | next_url = url['url'] |
2278 | matchgroups = re.search(r"max_id=([0-9]*)", next_url) | 2278 | matchgroups = re.search(r"[?&]max_id=([^&]+)", next_url) |
2279 | 2279 | ||
2280 | if matchgroups: | 2280 | if matchgroups: |
2281 | next_params = copy.deepcopy(params) | 2281 | next_params = copy.deepcopy(params) |
2282 | next_params['_pagination_method'] = method | 2282 | next_params['_pagination_method'] = method |
2283 | next_params['_pagination_endpoint'] = endpoint | 2283 | next_params['_pagination_endpoint'] = endpoint |
2284 | next_params['max_id'] = int(matchgroups.group(1)) | 2284 | max_id = matchgroups.group(1) |
2285 | if max_id.isdigit(): | ||
2286 | next_params['max_id'] = int(max_id) | ||
2287 | else: | ||
2288 | next_params['max_id'] = max_id | ||
2285 | if "since_id" in next_params: | 2289 | if "since_id" in next_params: |
2286 | del next_params['since_id'] | 2290 | del next_params['since_id'] |
2287 | response[-1]._pagination_next = next_params | 2291 | response[-1]._pagination_next = next_params |
@@ -2289,13 +2293,17 @@ class Mastodon: | |||
2289 | if url['rel'] == 'prev': | 2293 | if url['rel'] == 'prev': |
2290 | # Be paranoid and extract since_id specifically | 2294 | # Be paranoid and extract since_id specifically |
2291 | prev_url = url['url'] | 2295 | prev_url = url['url'] |
2292 | matchgroups = re.search(r"since_id=([0-9]*)", prev_url) | 2296 | matchgroups = re.search(r"[?&]since_id=([^&]+)", prev_url) |
2293 | 2297 | ||
2294 | if matchgroups: | 2298 | if matchgroups: |
2295 | prev_params = copy.deepcopy(params) | 2299 | prev_params = copy.deepcopy(params) |
2296 | prev_params['_pagination_method'] = method | 2300 | prev_params['_pagination_method'] = method |
2297 | prev_params['_pagination_endpoint'] = endpoint | 2301 | prev_params['_pagination_endpoint'] = endpoint |
2298 | prev_params['since_id'] = int(matchgroups.group(1)) | 2302 | since_id = matchgroups.group(1) |
2303 | if since_id.isdigit(): | ||
2304 | prev_params['since_id'] = int(since_id) | ||
2305 | else: | ||
2306 | prev_params['since_id'] = since_id | ||
2299 | if "max_id" in prev_params: | 2307 | if "max_id" in prev_params: |
2300 | del prev_params['max_id'] | 2308 | del prev_params['max_id'] |
2301 | response[0]._pagination_prev = prev_params | 2309 | response[0]._pagination_prev = prev_params |
@@ -1,6 +1,6 @@ | |||
1 | from setuptools import setup | 1 | from setuptools import setup |
2 | 2 | ||
3 | test_deps = ['pytest', 'pytest-runner', 'pytest-cov', 'vcrpy', 'pytest-vcr', 'pytest-mock'] | 3 | test_deps = ['pytest', 'pytest-runner', 'pytest-cov', 'vcrpy', 'pytest-vcr', 'pytest-mock', 'requests-mock'] |
4 | extras = { | 4 | extras = { |
5 | "test": test_deps | 5 | "test": test_deps |
6 | } | 6 | } |
diff --git a/tests/test_pagination.py b/tests/test_pagination.py index 599b2f4..d2c0bd5 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py | |||
@@ -1,5 +1,10 @@ | |||
1 | import pytest | 1 | import pytest |
2 | from contextlib import contextmanager | 2 | from contextlib import contextmanager |
3 | try: | ||
4 | from mock import MagicMock | ||
5 | except ImportError: | ||
6 | from unittest.mock import MagicMock | ||
7 | import requests_mock | ||
3 | 8 | ||
4 | UNLIKELY_HASHTAG = "fgiztsshwiaqqiztpmmjbtvmescsculuvmgjgopwoeidbcrixp" | 9 | UNLIKELY_HASHTAG = "fgiztsshwiaqqiztpmmjbtvmescsculuvmgjgopwoeidbcrixp" |
5 | 10 | ||
@@ -44,3 +49,18 @@ def test_fetch_remaining(api): | |||
44 | hashtag_remaining = api.fetch_remaining(hashtag) | 49 | hashtag_remaining = api.fetch_remaining(hashtag) |
45 | assert hashtag_remaining | 50 | assert hashtag_remaining |
46 | assert len(hashtag_remaining) >= 30 | 51 | assert len(hashtag_remaining) >= 30 |
52 | |||
53 | def test_link_headers(api): | ||
54 | rmock = requests_mock.Adapter() | ||
55 | api.session.mount(api.api_base_url, rmock) | ||
56 | |||
57 | _id='abc1234' | ||
58 | |||
59 | rmock.register_uri('GET', requests_mock.ANY, json=[{"foo": "bar"}], headers={"link":""" | ||
60 | <{base}/api/v1/timelines/tag/{tag}?max_id={_id}>; rel="next", <{base}/api/v1/timelines/tag/{tag}?since_id={_id}>; rel="prev" | ||
61 | """.format(base=api.api_base_url, tag=UNLIKELY_HASHTAG, _id=_id).strip() | ||
62 | }) | ||
63 | |||
64 | resp = api.timeline_hashtag(UNLIKELY_HASHTAG) | ||
65 | assert resp[0]._pagination_next['max_id'] == _id | ||
66 | assert resp[0]._pagination_prev['since_id'] == _id | ||