From 1d730394748ed25ba94a1c70dcda57c0859aacd8 Mon Sep 17 00:00:00 2001 From: "Daniel S. Billing" Date: Mon, 27 Nov 2023 21:51:02 +0100 Subject: [PATCH] Added functions to get API version --- requirements.txt | 2 +- tests/test_api.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++ tunsberg/api.py | 52 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 tests/test_api.py create mode 100644 tunsberg/api.py diff --git a/requirements.txt b/requirements.txt index 8b13789..bece863 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ - +flask>=2.3.0,>=3.0.0 diff --git a/tests/test_api.py b/tests/test_api.py new file mode 100644 index 0000000..e7d769c --- /dev/null +++ b/tests/test_api.py @@ -0,0 +1,61 @@ +from flask import Flask + +from tunsberg.api import get_api_version, get_api_version_from_flask_url + + +app = Flask(__name__) + + +def test_get_api_version_from_flask_url_default(): + """ Test that the default pattern matches """ + with app.test_request_context('/api/v1/resource'): + assert get_api_version_from_flask_url() == 'v1' + + +def test_get_api_version_from_flask_url_custom_pattern(): + """ Test that the custom pattern matches """ + with app.test_request_context('/api/v2_1/resource'): + assert get_api_version_from_flask_url(pattern=r'v\d+_\d+') == 'v2_1' + + +def test_get_api_version_from_flask_url_no_version(): + """ Test that the default return value is empty string """ + with app.test_request_context('/api/resource'): + assert get_api_version_from_flask_url() == '' + + +def test_get_api_version_from_flask_url_default_return(): + """ Test that the default return value is 'v0' """ + with app.test_request_context('/api/resource'): + assert get_api_version_from_flask_url(default='v0') == 'v0' + + +def test_get_api_version_from_flask_url_no_default_return(): + """ Test that the default return value is empty string """ + with app.test_request_context('/api/resource'): + assert get_api_version_from_flask_url(default='') == '' + + +def test_get_api_version_standard(): + """ Test that the standard pattern matches """ + assert get_api_version('app.api.v1') == 'v1' + assert get_api_version('module.v2.submodule') == 'v2' + assert get_api_version('service.v3_1.beta') == 'v3_1' + + +def test_get_api_version_no_version(): + """ Test that the default return value is empty string """ + assert get_api_version('app.api') == '' + assert get_api_version('module.submodule') == '' + + +def test_get_api_version_custom_pattern(): + """ Test that the custom pattern matches """ + assert get_api_version('app.api.v2021_04', pattern=r'v\d{4}_\d{2}') == 'v2021_04' + assert get_api_version('service.v2021.beta', pattern=r'v\d{4}') == 'v2021' + + +def test_get_api_version_custom_default(): + """ Test that the custom default value is returned """ + assert get_api_version('app.api', default='no_version') == 'no_version' + assert get_api_version('module.submodule', default='undefined') == 'undefined' diff --git a/tunsberg/api.py b/tunsberg/api.py new file mode 100644 index 0000000..b51f6b0 --- /dev/null +++ b/tunsberg/api.py @@ -0,0 +1,52 @@ +import re + +from flask import request + + +def get_api_version(folder_name: str, pattern: str = r'v\d+(_\d+)?', default: str = '') -> str: + r""" + Get API version from folder name. + + :param folder_name: Folder name + :type folder_name: str + :param pattern: Regular expression pattern to match version. Default is 'v\\d+(_\\d+)?', + which matches 'v' or 'v_'. + :type pattern: str + :param default: Default return value if no version is found. Defaults to ''. + :type default: str + :return: API version as string, or the default value if no version is found + :rtype: str + """ + if folder_name == 'app.api': + return default + + version_parts = folder_name.split('.') + version_regex = re.compile(pattern) + + for part in version_parts: + if version_regex.match(part): + return part + + return default + + +def get_api_version_from_flask_url(pattern: str = r'v\d+(_\d+)?', default: str = '') -> str: + r""" + Get the API version from a Flask URL. + + :param pattern: Regular expression pattern to match version. Default is 'v\\d+(_\\d+)?', + which matches 'v' or 'v_'. + :type pattern: str + :param default: Default return value if no version is found. Defaults to ''. + :type default: str + :return: API version as string, or the default value if no version is found + :rtype: str + """ + url_list = request.url.split('/') + version_regex = re.compile(pattern) + + for item in url_list: + if version_regex.match(item): + return item + + return default