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 98ac72a..c22cabe 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 |
@@ -3040,8 +3057,8 @@ class Mastodon: | |||
3040 | Returns the next page or None if no further data is available. | 3057 | Returns the next page or None if no further data is available. |
3041 | """ | 3058 | """ |
3042 | if isinstance(previous_page, list) and len(previous_page) != 0: | 3059 | if isinstance(previous_page, list) and len(previous_page) != 0: |
3043 | if hasattr(previous_page[-1], '_pagination_next'): | 3060 | if hasattr(previous_page, '_pagination_next'): |
3044 | params = copy.deepcopy(previous_page[-1]._pagination_next) | 3061 | params = copy.deepcopy(previous_page._pagination_next) |
3045 | else: | 3062 | else: |
3046 | return None | 3063 | return None |
3047 | else: | 3064 | else: |
@@ -3064,8 +3081,8 @@ class Mastodon: | |||
3064 | Returns the previous page or None if no further data is available. | 3081 | Returns the previous page or None if no further data is available. |
3065 | """ | 3082 | """ |
3066 | if isinstance(next_page, list) and len(next_page) != 0: | 3083 | if isinstance(next_page, list) and len(next_page) != 0: |
3067 | if hasattr(next_page[0], '_pagination_prev'): | 3084 | if hasattr(next_page, '_pagination_prev'): |
3068 | params = copy.deepcopy(next_page[0]._pagination_prev) | 3085 | params = copy.deepcopy(next_page._pagination_prev) |
3069 | else: | 3086 | else: |
3070 | return None | 3087 | return None |
3071 | else: | 3088 | else: |
@@ -3443,6 +3460,7 @@ class Mastodon: | |||
3443 | if isinstance(response, list) and \ | 3460 | if isinstance(response, list) and \ |
3444 | 'Link' in response_object.headers and \ | 3461 | 'Link' in response_object.headers and \ |
3445 | response_object.headers['Link'] != "": | 3462 | response_object.headers['Link'] != "": |
3463 | response = AttribAccessList(response) | ||
3446 | tmp_urls = requests.utils.parse_header_links( | 3464 | tmp_urls = requests.utils.parse_header_links( |
3447 | response_object.headers['Link'].rstrip('>').replace('>,<', ',<')) | 3465 | response_object.headers['Link'].rstrip('>').replace('>,<', ',<')) |
3448 | for url in tmp_urls: | 3466 | for url in tmp_urls: |
@@ -3467,7 +3485,7 @@ class Mastodon: | |||
3467 | del next_params['since_id'] | 3485 | del next_params['since_id'] |
3468 | if "min_id" in next_params: | 3486 | if "min_id" in next_params: |
3469 | del next_params['min_id'] | 3487 | del next_params['min_id'] |
3470 | response[-1]._pagination_next = next_params | 3488 | response._pagination_next = next_params |
3471 | 3489 | ||
3472 | if url['rel'] == 'prev': | 3490 | if url['rel'] == 'prev': |
3473 | # Be paranoid and extract since_id or min_id specifically | 3491 | # Be paranoid and extract since_id or min_id specifically |
@@ -3486,7 +3504,7 @@ class Mastodon: | |||
3486 | prev_params['since_id'] = since_id | 3504 | prev_params['since_id'] = since_id |
3487 | if "max_id" in prev_params: | 3505 | if "max_id" in prev_params: |
3488 | del prev_params['max_id'] | 3506 | del prev_params['max_id'] |
3489 | response[0]._pagination_prev = prev_params | 3507 | response._pagination_prev = prev_params |
3490 | 3508 | ||
3491 | # New and fantastico (post-2.6.0): min_id pagination | 3509 | # New and fantastico (post-2.6.0): min_id pagination |
3492 | matchgroups = re.search(r"[?&]min_id=([^&]+)", prev_url) | 3510 | matchgroups = re.search(r"[?&]min_id=([^&]+)", prev_url) |
@@ -3501,7 +3519,7 @@ class Mastodon: | |||
3501 | prev_params['min_id'] = min_id | 3519 | prev_params['min_id'] = min_id |
3502 | if "max_id" in prev_params: | 3520 | if "max_id" in prev_params: |
3503 | del prev_params['max_id'] | 3521 | del prev_params['max_id'] |
3504 | response[0]._pagination_prev = prev_params | 3522 | response._pagination_prev = prev_params |
3505 | 3523 | ||
3506 | return response | 3524 | return response |
3507 | 3525 | ||
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 |