Repository navigation
feat(core): add runtime Python version support warning for EoL versions - #997
lahirumaramba wants to merge 1 commit into
Conversation
Add _python_version_support module (adapted from google-api-core) and invoke check_python_version(package='firebase-admin') at package import time to emit a FutureWarning on deprecated and End-of-Life Python versions (<= 3.10).
There was a problem hiding this comment.
Code Review
This pull request introduces a Python version support check mechanism for the Firebase Admin Python SDK, deprecating support for Python 3.9 and 3.10. It adds a new _python_version_support module to check the running Python version against predefined EOL dates, integrates this check into the package initialization, and includes comprehensive unit tests. The review feedback highlights a logical bug in the EOL warning date calculation that limits the warning to a single day, an incorrect package name string passed to the version check that bypasses distribution mapping, and the corresponding test updates needed to reflect the corrected EOL logic.
| warnings.warn(message, FutureWarning) | ||
| return PythonVersionStatus.PYTHON_VERSION_UNSUPPORTED | ||
|
|
||
| eol_date = version_info.python_eol + EOL_GRACE_PERIOD |
There was a problem hiding this comment.
eol_date is currently calculated as version_info.python_eol + EOL_GRACE_PERIOD. Since gapic_end also defaults to version_info.python_eol + EOL_GRACE_PERIOD, this means eol_date and gapic_end are identical by default. As a result, the PYTHON_VERSION_EOL warning is only active for exactly one day. For any day between python_eol and gapic_end - 1 day (the grace period), the code falls back to returning PYTHON_VERSION_DEPRECATED. This causes the deprecation warning to be shown after the Python version has already reached its EOL, resulting in a confusing message that says "once it reaches its end of life ({version_info.python_eol})" even though that date is in the past. Changing eol_date to version_info.python_eol ensures that the EOL warning is correctly shown starting from the actual EOL date up to gapic_end.
| eol_date = version_info.python_eol + EOL_GRACE_PERIOD | |
| eol_date = version_info.python_eol |
|
|
||
|
|
||
| # Perform Python version check and emit a support warning if needed. | ||
| _python_version_support.check_python_version(package='firebase-admin') |
There was a problem hiding this comment.
The package name passed to check_python_version is 'firebase-admin'. However, the automatic package distribution mapping in _get_distribution_and_import_packages expects the importable module name (which is 'firebase_admin') to resolve it to the PyPI distribution name. By passing 'firebase-admin' directly, the mapping logic is bypassed because 'firebase-admin' is not a key in packages_distributions(). Passing 'firebase_admin' instead will allow the mapping to succeed and produce a more informative warning message like package firebase-admin (firebase_admin).
| _python_version_support.check_python_version(package='firebase-admin') | |
| _python_version_support.check_python_version(package='firebase_admin') |
| test_cases = { | ||
| 'supported_before_deprecation_date': { | ||
| 'date': gapic_dep - datetime.timedelta(days=1), | ||
| 'expected': PythonVersionStatus.PYTHON_VERSION_SUPPORTED, | ||
| }, | ||
| 'deprecated_on_deprecation_date': { | ||
| 'date': gapic_dep, | ||
| 'expected': PythonVersionStatus.PYTHON_VERSION_DEPRECATED, | ||
| }, | ||
| 'deprecated_on_eol_date': { | ||
| 'date': version_info.python_eol, | ||
| 'expected': PythonVersionStatus.PYTHON_VERSION_DEPRECATED, | ||
| }, | ||
| 'deprecated_before_eol_warning_starts': { | ||
| 'date': eol_warning_starts - datetime.timedelta(days=1), | ||
| 'expected': PythonVersionStatus.PYTHON_VERSION_DEPRECATED, | ||
| }, | ||
| 'eol_on_eol_warning_date': { | ||
| 'date': eol_warning_starts, | ||
| 'expected': PythonVersionStatus.PYTHON_VERSION_EOL, | ||
| }, | ||
| 'eol_on_gapic_end_date': { | ||
| 'date': gapic_end, | ||
| 'expected': PythonVersionStatus.PYTHON_VERSION_EOL, | ||
| }, | ||
| 'unsupported_after_gapic_end_date': { | ||
| 'date': gapic_end + datetime.timedelta(days=1), | ||
| 'expected': PythonVersionStatus.PYTHON_VERSION_UNSUPPORTED, | ||
| }, | ||
| } |
There was a problem hiding this comment.
Since we are changing eol_date to version_info.python_eol, the test cases in get_tracked_version_test_cases need to be updated to reflect that the EOL warning starts on the actual EOL date rather than after the grace period.
test_cases = {
'supported_before_deprecation_date': {
'date': gapic_dep - datetime.timedelta(days=1),
'expected': PythonVersionStatus.PYTHON_VERSION_SUPPORTED,
},
'deprecated_on_deprecation_date': {
'date': gapic_dep,
'expected': PythonVersionStatus.PYTHON_VERSION_DEPRECATED,
},
'deprecated_before_eol_date': {
'date': version_info.python_eol - datetime.timedelta(days=1),
'expected': PythonVersionStatus.PYTHON_VERSION_DEPRECATED,
},
'eol_on_eol_date': {
'date': version_info.python_eol,
'expected': PythonVersionStatus.PYTHON_VERSION_EOL,
},
'eol_on_gapic_end_date': {
'date': gapic_end,
'expected': PythonVersionStatus.PYTHON_VERSION_EOL,
},
'unsupported_after_gapic_end_date': {
'date': gapic_end + datetime.timedelta(days=1),
'expected': PythonVersionStatus.PYTHON_VERSION_UNSUPPORTED,
},
}|
Superseded by #998 |
Summary
Implements the policy to drop End-of-Life (EoL) Python versions in minor releases, aligning
firebase-adminwith Google Cloud Python client libraries andgoogle-api-core.Adds
firebase_admin/_python_version_support.py(adapted fromgoogle.api_core._python_version_supportat1ca1428andf442d1f) and invokescheck_python_version(package="firebase-admin")once at package import time infirebase_admin/__init__.py.Key Changes
firebase_admin/_python_version_support.py):google-api-corelifecycle defaults (gapic_deprecation = python_eol - 1 year,gapic_end = python_eol + 1 week) with no custom grace overrides.VersionInfoentry for Python3.9(PSF EoL2025-10-05) alongside Python3.10–3.14so that the warning recommends upgrading to at least Python3.11. With defaultgapic_end, both Python3.9and3.10(both past EoL) emit thePYTHON_VERSION_UNSUPPORTEDFutureWarning("You are using a non-supported Python version... upgrade to at least Python 3.11"), matching the upcoming removal of both3.9and3.10in the next minor release.FutureWarning(rather thanDeprecationWarning, which Python hides by default outside__main__) so developers see the warning in logs when importingfirebase_admin.firebase_admin/__init__.py(_python_version_support.check_python_version(package="firebase-admin")), consistent withgoogle.api_core.__init__.importlib.metadata.packages_distributions()usinggetattr(metadata, "packages_distributions", None)for Python 3.9 compatibility and only resolves the package label lazily when a warning is emitted.README.md):Supported Python Versionssection to note that Python 3.9 and 3.10 support is deprecated and will be dropped in an upcoming minor release, and recommends Python 3.11 or higher.tests/test_python_version_support.py):today=parameter) covering Python3.9,3.10, supported versions (3.11–3.14), untracked older (3.8) and future (3.15,40.0) versions, andgapic_deprecation/gapic_endoverrides.Proposed Release Note
Testing
pytest tests/test_python_version_support.py tests/test_app.py(154 passed)pylint firebase_admin/__init__.py firebase_admin/_python_version_support.py tests/test_python_version_support.py(10.00/10)