nzbToMedia/eol.py
Clinton Hall f98d6fff65
Add Python 3.12 and fix Radarr handling (#1989)
* Added Python3.12 and future 3.13

* Fix Radarr result handling

* remove py2.7 and py3.7 support
2024-02-28 15:47:04 +13:00

193 lines
5.4 KiB
Python

#!/usr/bin/env python
from __future__ import (
absolute_import,
division,
print_function,
unicode_literals,
)
import datetime
import sys
import warnings
__version__ = '1.0.0'
def date(string, fmt='%Y-%m-%d'):
"""
Convert date string to date.
:param string: A date string
:param fmt: Format to use when parsing the date string
:return: A datetime.date
"""
return datetime.datetime.strptime(string, fmt).date()
# https://devguide.python.org/
# https://devguide.python.org/devcycle/#devcycle
PYTHON_EOL = {
(3, 13): date('2029-10-1'),
(3, 12): date('2028-10-1'),
(3, 11): date('2027-10-1'),
(3, 10): date('2026-10-01'),
(3, 9): date('2025-10-05'),
(3, 8): date('2024-10-14'),
(3, 7): date('2023-06-27'),
(3, 6): date('2021-12-23'),
(3, 5): date('2020-09-13'),
(3, 4): date('2019-03-16'),
(3, 3): date('2017-09-29'),
(3, 2): date('2016-02-20'),
(3, 1): date('2012-04-09'),
(3, 0): date('2009-01-13'),
(2, 7): date('2020-01-01'),
(2, 6): date('2013-10-29'),
}
class Error(Exception):
"""An error has occurred."""
class LifetimeError(Error):
"""Lifetime has been exceeded and upgrade is required."""
class LifetimeWarning(Warning):
"""Lifetime has been exceeded and is no longer supported."""
def lifetime(version=None):
"""
Calculate days left till End-of-Life for a version.
:param version: An optional tuple with version information
If a version is not provided, the current system version will be used.
:return: Days left until End-of-Life
"""
if version is None:
version = sys.version_info
major = version[0]
minor = version[1]
now = datetime.datetime.now().date()
time_left = PYTHON_EOL[(major, minor)] - now
return time_left.days
def expiration(version=None, grace_period=0):
"""
Calculate expiration date for a version given a grace period.
:param version: An optional tuple with version information
If a version is not provided, the current system version will be used.
:param grace_period: An optional number of days grace period
:return: Total days till expiration
"""
days_left = lifetime(version)
return days_left + grace_period
def check(version=None, grace_period=0):
"""
Raise an exception if end of life has been reached and recommend upgrade.
:param version: An optional tuple with version information
If a version is not provided, the current system version will be used.
:param grace_period: An optional number of days grace period
If a grace period is not provided, a default 60 days grace period will
be used.
:return: None
"""
try:
raise_for_status(version, grace_period)
except LifetimeError as error:
print('Please use a newer version of Python.')
print_statuses()
sys.exit(error)
def raise_for_status(version=None, grace_period=0):
"""
Raise an exception if end of life has been reached.
:param version: An optional tuple with version information
If a version is not provided, the current system version will be used.
:param grace_period: An optional number of days grace period
If a grace period is not provided, a default 60 days grace period will
be used.
:return: None
"""
if version is None:
version = sys.version_info
days_left = lifetime(version)
expires = days_left + grace_period
if expires <= 0:
msg = 'Python {major}.{minor} is no longer supported.'.format(
major=version[0],
minor=version[1],
)
raise LifetimeError(msg)
def warn_for_status(version=None, grace_period=0):
"""
Warn if end of life has been reached.
:param version: An optional tuple with version information
If a version is not provided, the current system version will be used.
:param grace_period: An optional number of days grace period
:return: None
"""
if version is None:
version = sys.version_info
days_left = lifetime(version)
expires = days_left + grace_period
if expires <= 0:
msg = 'Python {major}.{minor} is no longer supported.'.format(
major=version[0],
minor=version[1],
)
warnings.warn(msg, LifetimeWarning)
def print_statuses(show_expired=False):
"""
Print end-of-life statuses of known python versions.
:param show_expired: If true also print expired python version statuses
"""
lifetimes = sorted(
(lifetime(python_version), python_version)
for python_version in PYTHON_EOL
)
print('Python End-of-Life for current versions:')
for days_left, python_version in lifetimes:
if days_left >= 0:
print(
'v{major}.{minor} in {remaining:>4} days'.format(
major=python_version[0],
minor=python_version[1],
remaining=days_left,
),
)
if not show_expired:
return
print()
print('Python End-of-Life for expired versions:')
for days_left, python_version in lifetimes:
if days_left < 0:
print(
'v{major}.{minor} {remaining:>4} days ago'.format(
major=python_version[0],
minor=python_version[1],
remaining=-days_left,
),
)
if __name__ == '__main__':
print_statuses(show_expired=True)