diff --git a/rollbar/contrib/fastapi/utils.py b/rollbar/contrib/fastapi/utils.py index 74186133..db4902ec 100644 --- a/rollbar/contrib/fastapi/utils.py +++ b/rollbar/contrib/fastapi/utils.py @@ -21,6 +21,33 @@ def __init__(self, version, reason=''): return super().__init__(err_msg) +def is_current_version_higher_or_equal(current_version, min_version): + """ + Compare two version strings and return True if the current version is higher or equal to the minimum version. + + Note: This function only compares the release segment of the version string. + """ + def parse_version(version): + """Parse the release segment of a version string into a list of strings.""" + parsed = [''] + current_segment = 0 + for c in version: + if c.isdigit(): + parsed[current_segment] += c + elif c == '.': + current_segment += 1 + parsed.append('') + else: + break + if parsed[-1] == '': + parsed.pop() + return parsed + + current = tuple(map(int, parse_version(current_version))) + minimum = tuple(map(int, parse_version(min_version))) + return current >= minimum + + class fastapi_min_version: def __init__(self, min_version): self.min_version = min_version @@ -28,7 +55,10 @@ def __init__(self, min_version): def __call__(self, func): @functools.wraps(func) def wrapper(*args, **kwargs): - if fastapi.__version__ < self.min_version: + if not is_current_version_higher_or_equal( + fastapi.__version__, + self.min_version, + ): raise FastAPIVersionError( self.min_version, reason=f'to use {func.__name__}() function' ) diff --git a/rollbar/test/fastapi_tests/test_utils.py b/rollbar/test/fastapi_tests/test_utils.py index db14e126..549e9b8c 100644 --- a/rollbar/test/fastapi_tests/test_utils.py +++ b/rollbar/test/fastapi_tests/test_utils.py @@ -121,3 +121,35 @@ async def read_root(): app.include_router(router) self.assertFalse(has_bare_routing(app)) + +@unittest.skipUnless( + FASTAPI_INSTALLED and ALLOWED_PYTHON_VERSION, 'FastAPI requires Python3.6+' +) +class UtilsVersionCompareTest(BaseTest): + def test_is_current_version_higher_or_equal(self): + # Copied from https://semver.org/#spec-item-11 + versions = [ + '1.0.0-alpha', + '1.0.0-alpha.1', + '1.0.0-alpha.beta', + '1.0.0-beta', + '1.0.0-beta.2', + '1.0.0-beta.11', + '1.0.0-rc.1', + '1.0.0', + '1.1.1', + '1.100.0-beta2', + '1.100.0-beta3', + ] + + from rollbar.contrib.fastapi.utils import is_current_version_higher_or_equal + + previous_version = None + for version in versions: + print(f'{version} >= {previous_version}') + if previous_version is None: + previous_version = version + continue + with self.subTest(f'{version} >= {previous_version}'): + self.assertTrue(is_current_version_higher_or_equal(version, previous_version)) + previous_version = version