Skip to content

Commit

Permalink
have a version check timeout (#541)
Browse files Browse the repository at this point in the history
  • Loading branch information
MalteEbner authored Nov 1, 2021
1 parent 456bba3 commit 390558f
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 18 deletions.
24 changes: 12 additions & 12 deletions lightly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
__name__ = 'lightly'
__version__ = '1.1.21'

from multiprocessing import current_process
import os

try:
# See (https://github.com/PyTorchLightning/pytorch-lightning)
Expand Down Expand Up @@ -118,16 +118,16 @@ def _is_prefetch_generator_available():
from lightly import openapi_generated
from lightly import transforms
from lightly import utils

from lightly.api.version_checking import do_version_check

if os.getenv('LIGHTLY_DID_VERSION_CHECK', 'False') == 'False':
os.environ['LIGHTLY_DID_VERSION_CHECK'] = 'True'

try:
do_version_check(current_version=__version__)
except Exception as e:
pass


if current_process().name == 'MainProcess':
# check for latest version
from lightly.api.version_checking import get_latest_version
from lightly.api.version_checking import version_compare
from lightly.api.version_checking import pretty_print_latest_version

latest_version = get_latest_version(__version__)
if latest_version is not None:
if version_compare(__version__, latest_version) < 0:
# local version is behind latest version
pretty_print_latest_version(latest_version)

39 changes: 35 additions & 4 deletions lightly/api/version_checking.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import signal
import warnings
from multiprocessing import current_process
from typing import Tuple

import requests
Expand All @@ -9,7 +11,36 @@
from lightly.openapi_generated.swagger_client.configuration import Configuration
from lightly.api.utils import getenv

from lightly import __version__

class LightlyAPITimeoutException(Exception):
pass

class TimeoutDecorator:
def __init__(self, seconds):
self.seconds = seconds

def handle_timeout_method(self, *args, **kwargs):
raise LightlyAPITimeoutException

def __enter__(self):
signal.signal(signal.SIGALRM, self.handle_timeout_method)
signal.alarm(self.seconds)

def __exit__(self, exc_type, exc_val, exc_tb):
signal.alarm(0)


def do_version_check(current_version: str):
if current_process().name == 'MainProcess':
with TimeoutDecorator(1):
versioning_api = get_versioning_api()
current_version: str = versioning_api.get_latest_pip_version(
current_version=current_version)
latest_version: str = versioning_api.get_minimum_compatible_pip_version()
if version_compare(current_version, latest_version) < 0:
# local version is behind latest version
pretty_print_latest_version(current_version, latest_version)



def get_versioning_api() -> VersioningApi:
Expand All @@ -23,7 +54,7 @@ def get_versioning_api() -> VersioningApi:
def get_latest_version(current_version: str) -> Tuple[None, str]:
try:
versioning_api = get_versioning_api()
version_number: str = versioning_api.get_latest_pip_version(current_version = current_version)
version_number: str = versioning_api.get_latest_pip_version(current_version=current_version)
return version_number
except Exception as e:
return None
Expand All @@ -49,8 +80,8 @@ def version_compare(v0, v1):
return 0


def pretty_print_latest_version(latest_version, width=70):
warning = f"You are using lightly version {__version__}. " \
def pretty_print_latest_version(current_version, latest_version, width=70):
warning = f"You are using lightly version {current_version}. " \
f"There is a newer version of the package available. " \
f"For compatability reasons, please upgrade your current version: " \
f"pip install lightly=={latest_version}"
Expand Down
40 changes: 38 additions & 2 deletions tests/api/test_version_checking.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import sys
import time
import unittest

import lightly
from lightly.api.version_checking import get_latest_version, version_compare, \
get_minimum_compatible_version, pretty_print_latest_version
get_minimum_compatible_version, pretty_print_latest_version, \
LightlyAPITimeoutException, do_version_check
from tests.api_workflow.mocked_api_workflow_client import MockedVersioningApi


Expand All @@ -27,4 +30,37 @@ def test_get_minimum_compatible_version(self):
get_minimum_compatible_version()

def test_pretty_print(self):
pretty_print_latest_version("1.1.1")
pretty_print_latest_version(current_version="curr", latest_version="1.1.1")

def test_version_check_timout_mocked(self):
"""
We cannot check for other errors as we don't know whether the
current LIGHTLY_SERVER_URL is
- unreachable (error in < 1 second)
- causing a timeout and thus raising a LightlyAPITimeoutException
- reachable (success in < 1 second
Thus this only checks that the actual lightly.do_version_check()
with needing >1s internally causes a LightlyAPITimeoutException
"""
try:
old_get_versioning_api = lightly.api.version_checking.get_versioning_api

def mocked_get_versioning_api_timeout():
time.sleep(10)
print("This line should never be reached, calling sys.exit()")
sys.exit()

lightly.api.version_checking.get_versioning_api = mocked_get_versioning_api_timeout

start_time = time.time()

with self.assertRaises(LightlyAPITimeoutException):
do_version_check(lightly.__version__)

duration = time.time() - start_time

self.assertLess(duration, 1.5)

finally:
lightly.api.version_checking.get_versioning_api = old_get_versioning_api

0 comments on commit 390558f

Please sign in to comment.