aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rst8
-rw-r--r--docs/index.rst1
-rw-r--r--mastodon/Mastodon.py64
-rw-r--r--tests/test_streaming.py4
4 files changed, 59 insertions, 18 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 5383275..f472941 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,14 @@ A note on versioning: This librarys major version will grow with the APIs
2version number. Breaking changes will be indicated by a change in the minor 2version number. Breaking changes will be indicated by a change in the minor
3(or major) version number, and will generally be avoided. 3(or major) version number, and will generally be avoided.
4 4
5v1.4.4
6------
7* Added streaming_health
8* Added support for local hashtag streams
9* Made blurhash an optional dependency (Thanks limburgher)
10* Fixed some things related to error handling (Thanks lefherz)
11* Fixed various small documentation issues (Thanks lefherz)
12
5v1.4.3 13v1.4.3
6------ 14------
7* BREAKING BUT ONLY FOR YOUR DEPLOY, POTENTIALLY: http_ece and cryptography are now optional dependencies, if you need full webpush crypto support add the "webpush" feature to your Mastodon.py requirements or require one or both manually in your own setup.py. 15* BREAKING BUT ONLY FOR YOUR DEPLOY, POTENTIALLY: http_ece and cryptography are now optional dependencies, if you need full webpush crypto support add the "webpush" feature to your Mastodon.py requirements or require one or both manually in your own setup.py.
diff --git a/docs/index.rst b/docs/index.rst
index 898c09a..1851b04 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1109,6 +1109,7 @@ various exceptions: `MastodonMalformedEventError` if a received event cannot be
1109.. automethod:: Mastodon.stream_local 1109.. automethod:: Mastodon.stream_local
1110.. automethod:: Mastodon.stream_hashtag 1110.. automethod:: Mastodon.stream_hashtag
1111.. automethod:: Mastodon.stream_list 1111.. automethod:: Mastodon.stream_list
1112.. automethod:: Mastodon.stream_healthy
1112 1113
1113StreamListener 1114StreamListener
1114~~~~~~~~~~~~~~ 1115~~~~~~~~~~~~~~
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py
index ca38708..4f51d0d 100644
--- a/mastodon/Mastodon.py
+++ b/mastodon/Mastodon.py
@@ -2534,6 +2534,16 @@ class Mastodon:
2534 """ 2534 """
2535 return self.__stream('/api/v1/streaming/direct', listener, run_async=run_async, timeout=timeout, reconnect_async=reconnect_async, reconnect_async_wait_sec=reconnect_async_wait_sec) 2535 return self.__stream('/api/v1/streaming/direct', listener, run_async=run_async, timeout=timeout, reconnect_async=reconnect_async, reconnect_async_wait_sec=reconnect_async_wait_sec)
2536 2536
2537 @api_version("2.5.0", "2.5.0", "2.5.0")
2538 def stream_healthy(self):
2539 """
2540 Returns without True if streaming API is okay, False or raises an error otherwise.
2541 """
2542 api_okay = self.__api_request('GET', '/api/v1/streaming/health', base_url_override = self.__get_streaming_base(), parse=False)
2543 if api_okay == b'OK':
2544 return True
2545 return False
2546
2537 ### 2547 ###
2538 # Internal helpers, dragons probably 2548 # Internal helpers, dragons probably
2539 ### 2549 ###
@@ -2641,12 +2651,13 @@ class Mastodon:
2641 isotime = isotime[:-2] + ":" + isotime[-2:] 2651 isotime = isotime[:-2] + ":" + isotime[-2:]
2642 return isotime 2652 return isotime
2643 2653
2644 def __api_request(self, method, endpoint, params={}, files={}, headers={}, access_token_override=None, do_ratelimiting=True, use_json = False): 2654 def __api_request(self, method, endpoint, params={}, files={}, headers={}, access_token_override=None, base_url_override=None, do_ratelimiting=True, use_json=False, parse=True):
2645 """ 2655 """
2646 Internal API request helper. 2656 Internal API request helper.
2647 """ 2657 """
2648 response = None 2658 response = None
2649 remaining_wait = 0 2659 remaining_wait = 0
2660
2650 # "pace" mode ratelimiting: Assume constant rate of requests, sleep a little less long than it 2661 # "pace" mode ratelimiting: Assume constant rate of requests, sleep a little less long than it
2651 # would take to not hit the rate limit at that request rate. 2662 # would take to not hit the rate limit at that request rate.
2652 if do_ratelimiting and self.ratelimit_method == "pace": 2663 if do_ratelimiting and self.ratelimit_method == "pace":
@@ -2673,8 +2684,13 @@ class Mastodon:
2673 if not access_token_override is None: 2684 if not access_token_override is None:
2674 headers['Authorization'] = 'Bearer ' + access_token_override 2685 headers['Authorization'] = 'Bearer ' + access_token_override
2675 2686
2687 # Determine base URL
2688 base_url = self.api_base_url
2689 if not base_url_override is None:
2690 base_url = base_url_override
2691
2676 if self.debug_requests: 2692 if self.debug_requests:
2677 print('Mastodon: Request to endpoint "' + endpoint + '" using method "' + method + '".') 2693 print('Mastodon: Request to endpoint "' + base_url + endpoint + '" using method "' + method + '".')
2678 print('Parameters: ' + str(params)) 2694 print('Parameters: ' + str(params))
2679 print('Headers: ' + str(headers)) 2695 print('Headers: ' + str(headers))
2680 print('Files: ' + str(files)) 2696 print('Files: ' + str(files))
@@ -2695,9 +2711,9 @@ class Mastodon:
2695 kwargs['data'] = params 2711 kwargs['data'] = params
2696 else: 2712 else:
2697 kwargs['json'] = params 2713 kwargs['json'] = params
2698 2714
2699 response_object = self.session.request( 2715 response_object = self.session.request(
2700 method, self.api_base_url + endpoint, **kwargs) 2716 method, base_url + endpoint, **kwargs)
2701 except Exception as e: 2717 except Exception as e:
2702 raise MastodonNetworkError("Could not complete request: %s" % e) 2718 raise MastodonNetworkError("Could not complete request: %s" % e)
2703 2719
@@ -2783,14 +2799,17 @@ class Mastodon:
2783 response_object.reason, 2799 response_object.reason,
2784 error_msg) 2800 error_msg)
2785 2801
2786 try: 2802 if parse == True:
2787 response = response_object.json(object_hook=self.__json_hooks) 2803 try:
2788 except: 2804 response = response_object.json(object_hook=self.__json_hooks)
2789 raise MastodonAPIError( 2805 except:
2790 "Could not parse response as JSON, response code was %s, " 2806 raise MastodonAPIError(
2791 "bad json content was '%s'" % (response_object.status_code, 2807 "Could not parse response as JSON, response code was %s, "
2792 response_object.content)) 2808 "bad json content was '%s'" % (response_object.status_code,
2793 2809 response_object.content))
2810 else:
2811 response = response_object.content
2812
2794 # Parse link headers 2813 # Parse link headers
2795 if isinstance(response, list) and \ 2814 if isinstance(response, list) and \
2796 'Link' in response_object.headers and \ 2815 'Link' in response_object.headers and \
@@ -2857,15 +2876,12 @@ class Mastodon:
2857 2876
2858 return response 2877 return response
2859 2878
2860 def __stream(self, endpoint, listener, params={}, run_async=False, timeout=__DEFAULT_STREAM_TIMEOUT, reconnect_async=False, reconnect_async_wait_sec=__DEFAULT_STREAM_RECONNECT_WAIT_SEC): 2879 def __get_streaming_base(self):
2861 """ 2880 """
2862 Internal streaming API helper. 2881 Internal streaming API helper.
2863 2882
2864 Returns a handle to the open connection that the user can close if they 2883 Returns the correct URL for the streaming API.
2865 wish to terminate it.
2866 """ 2884 """
2867
2868 # Check if we have to redirect
2869 instance = self.instance() 2885 instance = self.instance()
2870 if "streaming_api" in instance["urls"] and instance["urls"]["streaming_api"] != self.api_base_url: 2886 if "streaming_api" in instance["urls"] and instance["urls"]["streaming_api"] != self.api_base_url:
2871 # This is probably a websockets URL, which is really for the browser, but requests can't handle it 2887 # This is probably a websockets URL, which is really for the browser, but requests can't handle it
@@ -2881,6 +2897,18 @@ class Mastodon:
2881 instance["urls"]["streaming_api"])) 2897 instance["urls"]["streaming_api"]))
2882 else: 2898 else:
2883 url = self.api_base_url 2899 url = self.api_base_url
2900 return url
2901
2902 def __stream(self, endpoint, listener, params={}, run_async=False, timeout=__DEFAULT_STREAM_TIMEOUT, reconnect_async=False, reconnect_async_wait_sec=__DEFAULT_STREAM_RECONNECT_WAIT_SEC):
2903 """
2904 Internal streaming API helper.
2905
2906 Returns a handle to the open connection that the user can close if they
2907 wish to terminate it.
2908 """
2909
2910 # Check if we have to redirect
2911 url = self.__get_streaming_base()
2884 2912
2885 # The streaming server can't handle two slashes in a path, so remove trailing slashes 2913 # The streaming server can't handle two slashes in a path, so remove trailing slashes
2886 if url[-1] == '/': 2914 if url[-1] == '/':
diff --git a/tests/test_streaming.py b/tests/test_streaming.py
index 2e52f35..a471c41 100644
--- a/tests/test_streaming.py
+++ b/tests/test_streaming.py
@@ -365,3 +365,7 @@ def test_stream_user_local(api, api2):
365 assert updates[0].id == posted[0].id 365 assert updates[0].id == posted[0].id
366 366
367 t.join() 367 t.join()
368
369@pytest.mark.vcr()
370def test_stream_healthy(api_anonymous):
371 assert api_anonymous.stream_healthy()
Powered by cgit v1.2.3 (git 2.41.0)