Add API version, warn if not present despite version >= 4.3.0

pull/419/head
Lorenz Diener 2025-08-15 13:02:50 +03:00
rodzic d959fa1906
commit 1af3e8d34d
3 zmienionych plików z 51 dodań i 16 usunięć

Wyświetl plik

@ -7,6 +7,9 @@ v2.1.0 (IN PROGRESS)
* Fixed to_json breaking on python 3.14 (Thanks @limburgher for the report) * Fixed to_json breaking on python 3.14 (Thanks @limburgher for the report)
* Replaced pytest-vcr (deprecated) with pytest-recording (Thanks @CyberTailor) * Replaced pytest-vcr (deprecated) with pytest-recording (Thanks @CyberTailor)
* Improved timeline documentation (Thanks @adamse) * Improved timeline documentation (Thanks @adamse)
* Improved docs for stream_healthy (thanks @codl)
* Add offset parameter to trending_tags and trending_links (Thanks @ghost)
* Added support for retrieving API version and a warning for if it is not present despite the mastodon version suggesting it should be.
v2.0.1 v2.0.1
------ ------
@ -313,7 +316,7 @@ of things changed, since this release covers two Mastodon versions and
then some !!!!! then some !!!!!
* Several small bug fixes (Thanks goldensuneur, bowlercaptain, joyeusenoelle) * Several small bug fixes (Thanks goldensuneur, bowlercaptain, joyeusenoelle)
* Improved stream error handling (Thanks codl) * Improved stream error handling (thanks @codl)
* Improvements to streaming: * Improvements to streaming:
* Added on_abort() handler to streams * Added on_abort() handler to streams
* Added automatic reconnecting * Added automatic reconnecting
@ -337,7 +340,7 @@ then some !!!!!
v1.2.2 v1.2.2
------ ------
* Several small bugfixes (thanks codl) * Several small bugfixes (thanks @codl)
* Mastodon v2.1.2 compatibility * Mastodon v2.1.2 compatibility
* Added instance_activity() * Added instance_activity()
* Added instance_peers() * Added instance_peers()
@ -371,17 +374,17 @@ v1.2.0
v1.1.2 v1.1.2
------ ------
* 2.0 id compatibility (thanks codl) * 2.0 id compatibility (thanks @codl)
* Added emoji support * Added emoji support
* Media alt-text support (thanks foozmeat) * Media alt-text support (thanks foozmeat)
* Python2 fixes (thanks ragingscholar) * Python2 fixes (thanks ragingscholar)
* General code cleanup and small fixes (thanks codl) * General code cleanup and small fixes (thanks @codl)
* Beginnings of better error handling (thanks Elizafox) * Beginnings of better error handling (thanks Elizafox)
* Various documentation updates * Various documentation updates
v1.1.1 v1.1.1
------ ------
* Emergency fix to allow logging in to work (thanks codl) * Emergency fix to allow logging in to work (thanks @codl)
v1.1.0 v1.1.0
------ ------

Wyświetl plik

@ -237,10 +237,20 @@ class Mastodon(Internals):
self.mastodon_major = 1 self.mastodon_major = 1
self.mastodon_minor = 0 self.mastodon_minor = 0
self.mastodon_patch = 0 self.mastodon_patch = 0
self.version_check_worked = None
self.version_check_tried = False # new addition from 4.3.0 on: API versioning.
# For now, we retrieve and cache this along with the other version information,
# though do not use it to do version checks (yet). TBD on whether to go through
# the trouble of doing this for all new endpoints, we'll have to see if other
# API implementations start using this (fingers crossed).
# We also emit a warning if the version is >= 4.3.0 but no API version is found.
self.mastodon_api_version = 0
self.__version_check_worked = None
self.__version_check_tried = False
if not mastodon_version is None: if not mastodon_version is None:
self.version_check_tried = True self.__version_check_tried = True
# Cached version check # Cached version check
self.__streaming_base = None self.__streaming_base = None
@ -264,9 +274,10 @@ class Mastodon(Internals):
* Mastodon version * Mastodon version
* Streaming base URL * Streaming base URL
""" """
self.version_check_worked = None self.__version_check_worked = None
self.version_check_tried = False self.__version_check_tried = False
self.__streaming_base = None self.__streaming_base = None
self.__oauth_grant_info = None
def auth_request_url(self, client_id: Optional[Union[str, PurePath]] = None, redirect_uris: str = "urn:ietf:wg:oauth:2.0:oob", def auth_request_url(self, client_id: Optional[Union[str, PurePath]] = None, redirect_uris: str = "urn:ietf:wg:oauth:2.0:oob",
scopes: List[str] =_DEFAULT_SCOPES, force_login: bool = False, state: Optional[str] = None, scopes: List[str] =_DEFAULT_SCOPES, force_login: bool = False, state: Optional[str] = None,
@ -336,11 +347,18 @@ class Mastodon(Internals):
Returns the access token as a string. Returns the access token as a string.
""" """
# Is the version > 4.4.0? Throw on trying to log in with password with a more informative message than the API error # Is the version > 4.4.0? Throw on trying to log in with password with a more informative message than the API error
# This is left in here even though we check for available grant types above because that way
# we can give a more informative error message to the user ("not supported after version 4.4.0") instead of the
# generic one.
if self.mastodon_major >= 4 and self.mastodon_minor >= 4 or self.mastodon_major > 4: if self.mastodon_major >= 4 and self.mastodon_minor >= 4 or self.mastodon_major > 4:
if password is not None: if password is not None:
raise MastodonIllegalArgumentError('Password flow is no longer supported in Mastodon 4.4.0 and later.') raise MastodonIllegalArgumentError('Password flow is no longer supported in Mastodon 4.4.0 and later.')
#
if username is not None and password is not None: if username is not None and password is not None:
params = self.__generate_params(locals(), ['scopes', 'to_file', 'code', 'refresh_token']) params = self.__generate_params(locals(), ['scopes', 'to_file', 'code', 'refresh_token'])
params['grant_type'] = 'password' params['grant_type'] = 'password'
@ -386,8 +404,9 @@ class Mastodon(Internals):
token_file.write(self.persistable_login_credentials()) token_file.write(self.persistable_login_credentials())
self.__logged_in_id = None self.__logged_in_id = None
# Retry version check if needed (might be required in limited federation mode) # Retry version check if needed (might be required in limited federation mode since
if not self.version_check_worked: # if the API is locked down, we need to auth before we can get the version)
if not self.__version_check_worked:
self.retrieve_mastodon_version() self.retrieve_mastodon_version()
return response['access_token'] return response['access_token']

Wyświetl plik

@ -4,6 +4,7 @@ import re
import dateutil import dateutil
import datetime import datetime
import copy import copy
import warnings
from mastodon.errors import MastodonAPIError, MastodonIllegalArgumentError from mastodon.errors import MastodonAPIError, MastodonIllegalArgumentError
from mastodon.compat import IMPL_HAS_BLURHASH, blurhash from mastodon.compat import IMPL_HAS_BLURHASH, blurhash
@ -32,13 +33,25 @@ class Mastodon(Internals):
""" """
try: try:
version_str = self.__normalize_version_string(self.__instance()["version"]) version_str = self.__normalize_version_string(self.__instance()["version"])
self.version_check_worked = True self.__version_check_worked = True
except Exception as e: except Exception as e:
# instance() was added in 1.1.0, so our best guess is 1.0.0. # instance() was added in 1.1.0, so our best guess is 1.0.0.
version_str = "1.0.0" version_str = "1.0.0"
self.version_check_worked = False self.__version_check_worked = False
self.mastodon_major, self.mastodon_minor, self.mastodon_patch = parse_version_string(version_str) self.mastodon_major, self.mastodon_minor, self.mastodon_patch = parse_version_string(version_str)
self.version_check_tried = True
# If the instance has an API version, we store that as well.
# If we have a version >= 4.3.0 but no API version, we throw a warning that this is a Weird Implementation,
# which might help with adoption of the API versioning or at least give us a better picture of how it is going.
found_api_version = False
if "api_versions" in self.__instance():
if "mastodon" in self.__instance()["api_versions"]:
self.mastodon_api_version = int(self.__instance()["api_versions"]["mastodon"])
found_api_version = True
if not found_api_version and self.mastodon_major >= 4 and self.mastodon_minor >= 3:
warnings.warn("Mastodon version is detected as >= 4.3.0, but no API version found. Please report this.")
self.__version_check_tried = True
return version_str return version_str
def verify_minimum_version(self, version_str, cached=False): def verify_minimum_version(self, version_str, cached=False):
@ -49,7 +62,7 @@ class Mastodon(Internals):
Returns True if version requirement is satisfied, False if not. Returns True if version requirement is satisfied, False if not.
""" """
if not cached or not self.version_check_tried: if not cached or not self.__version_check_tried:
self.retrieve_mastodon_version() self.retrieve_mastodon_version()
major, minor, patch = parse_version_string(version_str) major, minor, patch = parse_version_string(version_str)
if major > self.mastodon_major: if major > self.mastodon_major: