diff options
-rw-r--r-- | mastodon/Mastodon.py | 34 | ||||
-rw-r--r-- | tests/cassettes/test_domain_blocks.yaml | 7 | ||||
-rw-r--r-- | tests/test_pagination.py | 12 |
3 files changed, 37 insertions, 16 deletions
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py index 8b0afb3..0304b8f 100644 --- a/mastodon/Mastodon.py +++ b/mastodon/Mastodon.py | |||
@@ -120,10 +120,27 @@ class AttribAccessDict(dict): | |||
120 | raise AttributeError("Attribute-style access is read only") | 120 | raise AttributeError("Attribute-style access is read only") |
121 | super(AttribAccessDict, self).__setattr__(attr, val) | 121 | super(AttribAccessDict, self).__setattr__(attr, val) |
122 | 122 | ||
123 | |||
123 | ### | 124 | ### |
124 | # The actual Mastodon class | 125 | # List helper class. |
126 | # Defined at top level so it can be pickled. | ||
125 | ### | 127 | ### |
128 | class AttribAccessList(list): | ||
129 | def __getattr__(self, attr): | ||
130 | if attr in self: | ||
131 | return self[attr] | ||
132 | else: | ||
133 | raise AttributeError("Attribute not found: " + str(attr)) | ||
126 | 134 | ||
135 | def __setattr__(self, attr, val): | ||
136 | if attr in self: | ||
137 | raise AttributeError("Attribute-style access is read only") | ||
138 | super(AttribAccessList, self).__setattr__(attr, val) | ||
139 | |||
140 | |||
141 | ### | ||
142 | # The actual Mastodon class | ||
143 | ### | ||
127 | class Mastodon: | 144 | class Mastodon: |
128 | """ | 145 | """ |
129 | Thorough and easy to use Mastodon | 146 | Thorough and easy to use Mastodon |
@@ -3050,8 +3067,8 @@ class Mastodon: | |||
3050 | Returns the next page or None if no further data is available. | 3067 | Returns the next page or None if no further data is available. |
3051 | """ | 3068 | """ |
3052 | if isinstance(previous_page, list) and len(previous_page) != 0: | 3069 | if isinstance(previous_page, list) and len(previous_page) != 0: |
3053 | if hasattr(previous_page[-1], '_pagination_next'): | 3070 | if hasattr(previous_page, '_pagination_next'): |
3054 | params = copy.deepcopy(previous_page[-1]._pagination_next) | 3071 | params = copy.deepcopy(previous_page._pagination_next) |
3055 | else: | 3072 | else: |
3056 | return None | 3073 | return None |
3057 | else: | 3074 | else: |
@@ -3074,8 +3091,8 @@ class Mastodon: | |||
3074 | Returns the previous page or None if no further data is available. | 3091 | Returns the previous page or None if no further data is available. |
3075 | """ | 3092 | """ |
3076 | if isinstance(next_page, list) and len(next_page) != 0: | 3093 | if isinstance(next_page, list) and len(next_page) != 0: |
3077 | if hasattr(next_page[0], '_pagination_prev'): | 3094 | if hasattr(next_page, '_pagination_prev'): |
3078 | params = copy.deepcopy(next_page[0]._pagination_prev) | 3095 | params = copy.deepcopy(next_page._pagination_prev) |
3079 | else: | 3096 | else: |
3080 | return None | 3097 | return None |
3081 | else: | 3098 | else: |
@@ -3453,6 +3470,7 @@ class Mastodon: | |||
3453 | if isinstance(response, list) and \ | 3470 | if isinstance(response, list) and \ |
3454 | 'Link' in response_object.headers and \ | 3471 | 'Link' in response_object.headers and \ |
3455 | response_object.headers['Link'] != "": | 3472 | response_object.headers['Link'] != "": |
3473 | response = AttribAccessList(response) | ||
3456 | tmp_urls = requests.utils.parse_header_links( | 3474 | tmp_urls = requests.utils.parse_header_links( |
3457 | response_object.headers['Link'].rstrip('>').replace('>,<', ',<')) | 3475 | response_object.headers['Link'].rstrip('>').replace('>,<', ',<')) |
3458 | for url in tmp_urls: | 3476 | for url in tmp_urls: |
@@ -3477,7 +3495,7 @@ class Mastodon: | |||
3477 | del next_params['since_id'] | 3495 | del next_params['since_id'] |
3478 | if "min_id" in next_params: | 3496 | if "min_id" in next_params: |
3479 | del next_params['min_id'] | 3497 | del next_params['min_id'] |
3480 | response[-1]._pagination_next = next_params | 3498 | response._pagination_next = next_params |
3481 | 3499 | ||
3482 | if url['rel'] == 'prev': | 3500 | if url['rel'] == 'prev': |
3483 | # Be paranoid and extract since_id or min_id specifically | 3501 | # Be paranoid and extract since_id or min_id specifically |
@@ -3496,7 +3514,7 @@ class Mastodon: | |||
3496 | prev_params['since_id'] = since_id | 3514 | prev_params['since_id'] = since_id |
3497 | if "max_id" in prev_params: | 3515 | if "max_id" in prev_params: |
3498 | del prev_params['max_id'] | 3516 | del prev_params['max_id'] |
3499 | response[0]._pagination_prev = prev_params | 3517 | response._pagination_prev = prev_params |
3500 | 3518 | ||
3501 | # New and fantastico (post-2.6.0): min_id pagination | 3519 | # New and fantastico (post-2.6.0): min_id pagination |
3502 | matchgroups = re.search(r"[?&]min_id=([^&]+)", prev_url) | 3520 | matchgroups = re.search(r"[?&]min_id=([^&]+)", prev_url) |
@@ -3511,7 +3529,7 @@ class Mastodon: | |||
3511 | prev_params['min_id'] = min_id | 3529 | prev_params['min_id'] = min_id |
3512 | if "max_id" in prev_params: | 3530 | if "max_id" in prev_params: |
3513 | del prev_params['max_id'] | 3531 | del prev_params['max_id'] |
3514 | response[0]._pagination_prev = prev_params | 3532 | response._pagination_prev = prev_params |
3515 | 3533 | ||
3516 | return response | 3534 | return response |
3517 | 3535 | ||
diff --git a/tests/cassettes/test_domain_blocks.yaml b/tests/cassettes/test_domain_blocks.yaml index 8889bb1..041541e 100644 --- a/tests/cassettes/test_domain_blocks.yaml +++ b/tests/cassettes/test_domain_blocks.yaml | |||
@@ -10,10 +10,13 @@ interactions: | |||
10 | method: GET | 10 | method: GET |
11 | uri: http://localhost:3000/api/v1/domain_blocks | 11 | uri: http://localhost:3000/api/v1/domain_blocks |
12 | response: | 12 | response: |
13 | body: {string: '[]'} | 13 | body: {string: '["example.com"]'} |
14 | headers: | 14 | headers: |
15 | Cache-Control: ['no-cache, no-store'] | 15 | Cache-Control: ['no-cache, no-store'] |
16 | Content-Type: [application/json; charset=utf-8] | 16 | Content-Type: [application/json; charset=utf-8] |
17 | Link: ['<http://localhost:3000/api/v1/domain_blocks?max_id=10023>; | ||
18 | rel="next", <http://localhost:3000/api/v1/domain_blocks?min_id=10021>; | ||
19 | rel="prev"'] | ||
17 | Referrer-Policy: [strict-origin-when-cross-origin] | 20 | Referrer-Policy: [strict-origin-when-cross-origin] |
18 | Transfer-Encoding: [chunked] | 21 | Transfer-Encoding: [chunked] |
19 | Vary: ['Accept-Encoding, Origin'] | 22 | Vary: ['Accept-Encoding, Origin'] |
@@ -24,6 +27,6 @@ interactions: | |||
24 | X-Request-Id: [79ec8c37-a374-47e4-a698-a8b8511ca20f] | 27 | X-Request-Id: [79ec8c37-a374-47e4-a698-a8b8511ca20f] |
25 | X-Runtime: ['0.098492'] | 28 | X-Runtime: ['0.098492'] |
26 | X-XSS-Protection: [1; mode=block] | 29 | X-XSS-Protection: [1; mode=block] |
27 | content-length: ['2'] | 30 | content-length: ['15'] |
28 | status: {code: 200, message: OK} | 31 | status: {code: 200, message: OK} |
29 | version: 1 | 32 | version: 1 |
diff --git a/tests/test_pagination.py b/tests/test_pagination.py index 72ac06e..8a85ccb 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py | |||
@@ -39,9 +39,9 @@ def test_fetch_next_previous_from_pagination_info(api): | |||
39 | account = api.account_verify_credentials() | 39 | account = api.account_verify_credentials() |
40 | with many_statuses(api): | 40 | with many_statuses(api): |
41 | statuses = api.account_statuses(account['id'], limit=5) | 41 | statuses = api.account_statuses(account['id'], limit=5) |
42 | next_statuses = api.fetch_next(statuses[-1]._pagination_next) | 42 | next_statuses = api.fetch_next(statuses._pagination_next) |
43 | assert next_statuses | 43 | assert next_statuses |
44 | previous_statuses = api.fetch_previous(next_statuses[0]._pagination_prev) | 44 | previous_statuses = api.fetch_previous(next_statuses._pagination_prev) |
45 | assert previous_statuses | 45 | assert previous_statuses |
46 | 46 | ||
47 | def test_fetch_next_previous_old_pagination(api): | 47 | def test_fetch_next_previous_old_pagination(api): |
@@ -61,9 +61,9 @@ def test_fetch_next_previous_from_pagination_info_old_pagination(api): | |||
61 | 61 | ||
62 | with many_statuses(api): | 62 | with many_statuses(api): |
63 | statuses = api.account_statuses(account['id'], limit=5) | 63 | statuses = api.account_statuses(account['id'], limit=5) |
64 | next_statuses = api.fetch_next(statuses[-1]._pagination_next) | 64 | next_statuses = api.fetch_next(statuses._pagination_next) |
65 | assert next_statuses | 65 | assert next_statuses |
66 | previous_statuses = api.fetch_previous(next_statuses[0]._pagination_prev) | 66 | previous_statuses = api.fetch_previous(next_statuses._pagination_prev) |
67 | assert previous_statuses | 67 | assert previous_statuses |
68 | 68 | ||
69 | @pytest.mark.vcr() | 69 | @pytest.mark.vcr() |
@@ -86,5 +86,5 @@ def test_link_headers(api): | |||
86 | }) | 86 | }) |
87 | 87 | ||
88 | resp = api.timeline_hashtag(UNLIKELY_HASHTAG) | 88 | resp = api.timeline_hashtag(UNLIKELY_HASHTAG) |
89 | assert resp[0]._pagination_next['max_id'] == _id | 89 | assert resp._pagination_next['max_id'] == _id |
90 | assert resp[0]._pagination_prev['since_id'] == _id | 90 | assert resp._pagination_prev['since_id'] == _id |