From 037a6b5691df862447ded13a2d26962d4c5b3a12 Mon Sep 17 00:00:00 2001 From: sronilsson Date: Tue, 18 Feb 2025 10:40:36 -0500 Subject: [PATCH] gui version check --- setup.py | 2 +- simba/SimBA.py | 20 ++++++++++++-------- simba/utils/checks.py | 12 ++++++++++++ simba/utils/enums.py | 7 +++++-- simba/utils/lookups.py | 8 +++----- simba/utils/read_write.py | 32 ++++++++++++++++++++++++-------- simba/utils/warnings.py | 4 ++++ 7 files changed, 61 insertions(+), 24 deletions(-) diff --git a/setup.py b/setup.py index 91c85fd52..06e5c61e5 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ # Setup configuration setuptools.setup( name="simba_uw_tf_dev", - version="2.7.1", + version="2.7.2", author="Simon Nilsson, Jia Jie Choong, Sophia Hwang", author_email="sronilsson@gmail.com", description="Toolkit for computer classification and analysis of behaviors in experimental animals", diff --git a/simba/SimBA.py b/simba/SimBA.py index fa3760a8d..e9aa50fcf 100644 --- a/simba/SimBA.py +++ b/simba/SimBA.py @@ -1,6 +1,7 @@ __author__ = "Simon Nilsson" import os.path +import time import warnings warnings.filterwarnings("ignore", category=FutureWarning) @@ -23,8 +24,7 @@ from simba.bounding_box_tools.boundary_menus import BoundaryMenus from simba.cue_light_tools.cue_light_menues import CueLightAnalyzerMenu -from simba.labelling.labelling_advanced_interface import \ - select_labelling_video_advanced +from simba.labelling.labelling_advanced_interface import select_labelling_video_advanced from simba.labelling.labelling_interface import select_labelling_video from simba.labelling.targeted_annotations_clips import \ select_labelling_video_targeted_clips @@ -158,17 +158,15 @@ FileSelect, SimbaButton, SimBALabel, hxtScrollbar) from simba.ui.video_info_ui import VideoInfoTable -from simba.utils.checks import (check_ffmpeg_available, - check_file_exist_and_readable, check_int) +from simba.utils.checks import (check_ffmpeg_available, check_file_exist_and_readable, check_int) from simba.utils.custom_feature_extractor import CustomFeatureExtractor from simba.utils.enums import (OS, Defaults, Formats, Keys, Links, Paths, TagNames) from simba.utils.errors import InvalidInputError -from simba.utils.lookups import (get_bp_config_code_class_pairs, get_emojis, - get_icons_paths, load_simba_fonts) +from simba.utils.lookups import (get_bp_config_code_class_pairs, get_emojis, get_icons_paths, load_simba_fonts) from simba.utils.printing import stdout_success, stdout_warning -from simba.utils.read_write import find_core_cnt, get_video_meta_data -from simba.utils.warnings import FFMpegNotFoundWarning, PythonVersionWarning +from simba.utils.read_write import find_core_cnt, get_video_meta_data, fetch_pip_data +from simba.utils.warnings import FFMpegNotFoundWarning, PythonVersionWarning, VersionWarning from simba.video_processors.video_processing import \ extract_frames_from_all_videos_in_directory @@ -961,6 +959,12 @@ def __init__(self): if not check_ffmpeg_available(): FFMpegNotFoundWarning(msg='SimBA could not find a FFMPEG installation on computer (as evaluated by "ffmpeg" returning None). SimBA works best with FFMPEG and it is recommended to install it on your computer', source=self.__class__.__name__) + simba_pip_data = fetch_pip_data(pip_url=Links.SIMBA_PIP_URL.value) + if (simba_pip_data[1] is not None) and OS.SIMBA_VERSION.value is not None: + if simba_pip_data[1] != OS.SIMBA_VERSION.value: + msg = f"A new version of SimBA is available: {simba_pip_data[1]} (you have version {OS.SIMBA_VERSION.value}). Consider upgrading using: pip install simba-uw-tf-dev --upgrade" + VersionWarning(msg=msg) + def restart(self): confirm_restart = askyesno(title="RESTART", message="Are you sure that you want restart SimBA?") if confirm_restart: diff --git a/simba/utils/checks.py b/simba/utils/checks.py index ad09b717e..9d21ba5f6 100644 --- a/simba/utils/checks.py +++ b/simba/utils/checks.py @@ -690,6 +690,18 @@ def check_valid_hex_color(color_hex: str, raise_error: Optional[bool] = True) -> else: return True +def check_valid_url(url: str) -> bool: + """ Helper to check if a string is a valid url""" + regex = re.compile( + r'^(https?|ftp)://' # protocol + r'(\S+(:\S*)?@)?' # user:password (optional) + r'((\d{1,3}\.){3}\d{1,3}|' # IP address + r'([a-zA-Z0-9.-]+\.[a-zA-Z]{2,}))' # domain name + r'(:\d+)?' # port (optional) + r'(/[\S]*)?$', # path (optional) + re.IGNORECASE) + return re.match(regex, url) is not None + def check_if_2d_array_has_min_unique_values(data: np.ndarray, min: int) -> bool: """ diff --git a/simba/utils/enums.py b/simba/utils/enums.py index 1c19bace2..6872b0e47 100644 --- a/simba/utils/enums.py +++ b/simba/utils/enums.py @@ -9,7 +9,6 @@ import cv2 import numpy as np import pkg_resources - import simba @@ -119,6 +118,10 @@ class OS(Enum): LINUX = "Linux" MAC = "Darwin" PYTHON_VER = str(f"{sys.version_info.major}.{sys.version_info.minor}") + try: + SIMBA_VERSION = pkg_resources.get_distribution("simba-uw-tf-dev").version + except pkg_resources.DistributionNotFound: + SIMBA_VERSION = None class FontPaths(Enum): POPPINS_REGULAR = Path("assets/fonts/Poppins Regular.ttf") @@ -591,7 +594,7 @@ class Links(Enum): COUNT_ANNOTATIONS_IN_PROJECT = "https://github.com/sgoldenlab/simba/blob/master/docs/label_behavior.md#count-annotations-in-simba-project" COUNT_ANNOTATIONS_OUTSIDE_PROJECT = "https://github.com/sgoldenlab/simba/blob/master/docs/Tutorial_tools.md#extract-project-annotation-counts" CIRCLE_CROP = "https://github.com/sgoldenlab/simba/blob/master/docs/Tutorial_tools.md#circle-crop" - + SIMBA_PIP_URL = 'https://pypi.org/pypi/simba-uw-tf-dev/json' class Labelling(Enum): PADDING = 5 diff --git a/simba/utils/lookups.py b/simba/utils/lookups.py index 72d3d5deb..5b988614e 100644 --- a/simba/utils/lookups.py +++ b/simba/utils/lookups.py @@ -6,6 +6,8 @@ import re import struct import sys +import json +import urllib from multiprocessing import Lock, Value from pathlib import Path from typing import Dict, List, Tuple, Union @@ -16,8 +18,7 @@ from matplotlib import cm import simba -from simba.utils.checks import (check_file_exist_and_readable, - check_if_dir_exists) +from simba.utils.checks import (check_file_exist_and_readable, check_if_dir_exists) from simba.utils.enums import OS, UML, FontPaths, Methods, Paths from simba.utils.read_write import get_fn_ext from simba.utils.warnings import NoDataFoundWarning @@ -673,9 +674,6 @@ def get_model_names(): return list(pd.read_parquet(model_names_dir)[UML.NAMES.value]) - - - # # def rao_spacing_critical_values(): # {4.0: 186.45, diff --git a/simba/utils/read_write.py b/simba/utils/read_write.py index 1f398bb24..3f67b7b7f 100644 --- a/simba/utils/read_write.py +++ b/simba/utils/read_write.py @@ -29,6 +29,8 @@ from typing_extensions import Literal from urllib.parse import urlparse +from urllib import request + import cv2 import numpy as np @@ -37,8 +39,7 @@ import pyarrow as pa from numba import njit, prange from pyarrow import csv -from shapely.geometry import (LineString, MultiLineString, MultiPolygon, Point, - Polygon) +from shapely.geometry import (LineString, MultiLineString, MultiPolygon, Point, Polygon) import simba from simba.utils.checks import (check_file_exist_and_readable, check_float, @@ -50,8 +51,8 @@ check_int, check_nvidea_gpu_available, check_str, check_valid_array, check_valid_boolean, check_valid_dataframe, - check_valid_lst, is_video_color) -from simba.utils.enums import ConfigKey, Dtypes, Formats, Keys, Options, Paths + check_valid_lst, is_video_color, check_valid_url) +from simba.utils.enums import ConfigKey, Dtypes, Formats, Keys, Options, Paths, Links from simba.utils.errors import (DataHeaderError, DuplicationError, FFMPEGCodecGPUError, FileExistError, FrameRangeError, IntegerError, @@ -61,10 +62,7 @@ NoFilesFoundError, NotDirectoryError, ParametersFileError, PermissionError) from simba.utils.printing import SimbaTimer, stdout_success -from simba.utils.warnings import ( - FileExistWarning, FrameRangeWarning, InvalidValueWarning, - NoDataFoundWarning, NoFileFoundWarning, - ThirdPartyAnnotationsInvalidFileFormatWarning) +from simba.utils.warnings import (FileExistWarning, FrameRangeWarning, InvalidValueWarning, NoFileFoundWarning, ThirdPartyAnnotationsInvalidFileFormatWarning) SIMBA_DIR = os.path.dirname(simba.__file__) @@ -1776,6 +1774,24 @@ def get_pkg_version(pkg: str): except pkg_resources.DistributionNotFound: return None +def fetch_pip_data(pip_url: str = Links.SIMBA_PIP_URL.value) -> Union[Tuple[Dict[str, Any], str], Tuple[None, None]]: + """ Helper to fetch the pypi data associated with a package """ + if check_valid_url(url=pip_url): + try: + opener = request.build_opener(request.HTTPHandler(), request.HTTPSHandler()) + with opener.open(pip_url, timeout=2) as response: + if response.status == 200: + encoding = response.info().get_content_charset("utf-8") + data = response.read().decode(encoding) + json_data = json.loads(data) + latest_release = json_data.get("info", {}).get("version", "") + return json_data, latest_release + except Exception as e: + #print(e.args) + return None, None + else: + return None, None + def write_pickle(data: Dict[str, Any], save_path: Union[str, os.PathLike]) -> None: """ diff --git a/simba/utils/warnings.py b/simba/utils/warnings.py index 3bc42bf8d..21899fa40 100644 --- a/simba/utils/warnings.py +++ b/simba/utils/warnings.py @@ -264,3 +264,7 @@ def ResolutionWarning(msg: str, source: str = ""): @log_warning def GPUToolsWarning(msg: str, source: str = ""): pass + +@log_warning +def VersionWarning(msg: str, source: str = ""): + pass