diff --git a/pyproject.toml b/pyproject.toml index 7eee739cd..064321742 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ description = "ValidMind Library" license = "Commercial License" name = "validmind" readme = "README.pypi.md" -version = "2.8.1" +version = "2.8.2" [tool.poetry.dependencies] aiohttp = {extras = ["speedups"], version = "*"} diff --git a/validmind/__init__.py b/validmind/__init__.py index 99a3d0d2c..3099934ce 100644 --- a/validmind/__init__.py +++ b/validmind/__init__.py @@ -30,8 +30,12 @@ After you have pasted the code snippet into your development source code and executed the code, the Python Library API will register with ValidMind. You can now use the ValidMind Library to document and test your models, and to upload to the ValidMind Platform. """ +import threading import warnings +import pkg_resources +from IPython.display import HTML, display + # Ignore Numba warnings. We are not requiring this package directly from numba.core.errors import NumbaDeprecationWarning, NumbaPendingDeprecationWarning @@ -51,8 +55,46 @@ ) from .tests.decorator import tags, tasks, test from .tests.run import print_env +from .utils import is_notebook, parse_version from .vm_models.result import RawData +__shown = False + + +def show_warning(installed, running): + global __shown + + if __shown: + return + __shown = True + + message = ( + f"⚠️ This kernel is running an older version of validmind ({running}) " + f"than the latest version installed on your system ({installed}).\n\n" + "You may need to restart the kernel if you are experiencing issues." + ) + display(HTML(f"
{message}
")) + + +def check_version(): + # get the installed vs running version of validmind + # to make sure we are using the latest installed version + # in case user has updated the package but forgot to restart the kernel + installed = pkg_resources.get_distribution("validmind").version + running = __version__ + + if parse_version(installed) > parse_version(running): + show_warning(installed, running) + + # Schedule the next check for 5 minutes from now + timer = threading.Timer(300, check_version) + timer.daemon = True + timer.start() + + +if is_notebook(): + check_version() + __all__ = [ # noqa "__version__", # main library API diff --git a/validmind/__version__.py b/validmind/__version__.py index b4066b65a..239bf2b2b 100644 --- a/validmind/__version__.py +++ b/validmind/__version__.py @@ -1 +1 @@ -__version__ = "2.8.1" +__version__ = "2.8.2" diff --git a/validmind/utils.py b/validmind/utils.py index affcc31c3..7393b8883 100644 --- a/validmind/utils.py +++ b/validmind/utils.py @@ -60,6 +60,19 @@ logger = get_logger(__name__) +def parse_version(version: str) -> tuple[int, ...]: + """ + Parse a semver version string into a tuple of major, minor, patch integers + + Args: + version (str): The semantic version string to parse + + Returns: + tuple[int, ...]: A tuple of major, minor, patch integers + """ + return tuple(int(x) for x in version.split(".")[:3]) + + def is_notebook() -> bool: """ Checks if the code is running in a Jupyter notebook or IPython shell