From d5f231b10a22272ae9eab7f9830f7db69ea36b52 Mon Sep 17 00:00:00 2001 From: Abhi Date: Wed, 30 Oct 2019 14:58:24 -0600 Subject: [PATCH 1/2] Add check for new conrad version Add version check Add version check Made all changes as requested. Add function to check conrad version Add function to check for new conrad version --- conrad/__main__.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/conrad/__main__.py b/conrad/__main__.py index 9c195fe..eb6f207 100644 --- a/conrad/__main__.py +++ b/conrad/__main__.py @@ -1,7 +1,10 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import - +from __version__ import __version__ +from setuptools.version import pkg_resources +import requests +import logging __all__ = ("main",) @@ -12,5 +15,32 @@ def main(): cli() +def get_current_version(): + + url = "https://pypi.org/pypi/conference-radar/json" + response = requests.get(url) + if response: + data = response.json() + current_version = data["info"]["version"] + return current_version + return "" + + +def conrad_self_version_check(): + + current_version = get_current_version() + logger = logging.getLogger(__name__) + if current_version: + if pkg_resources.parse_version(__version__) <\ + pkg_resources.parse_version(current_version): + logger.warning("You are using conrad version %s; however," + " version %s is available.\n" + "You should consider upgrading via the " + "'pip install --upgrade conference-radar' command.\n", + __version__, current_version) + + if __name__ == "__main__": + + conrad_self_version_check() main() From 44b97a722a9b108df4463ef0f7729f18e22d97f1 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Thu, 30 Jul 2020 00:36:10 +0530 Subject: [PATCH 2/2] Move code to utils, add SelfCheckState and update entry points --- conrad/__main__.py | 35 ++-------------- conrad/utils.py | 100 ++++++++++++++++++++++++++++++++++++++++++++- setup.py | 2 +- 3 files changed, 102 insertions(+), 35 deletions(-) diff --git a/conrad/__main__.py b/conrad/__main__.py index eb6f207..8c7d307 100644 --- a/conrad/__main__.py +++ b/conrad/__main__.py @@ -1,10 +1,7 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import -from __version__ import __version__ -from setuptools.version import pkg_resources -import requests -import logging +from .utils import conrad_self_version_check + __all__ = ("main",) @@ -12,35 +9,9 @@ def main(): from conrad.cli import cli + conrad_self_version_check() cli() -def get_current_version(): - - url = "https://pypi.org/pypi/conference-radar/json" - response = requests.get(url) - if response: - data = response.json() - current_version = data["info"]["version"] - return current_version - return "" - - -def conrad_self_version_check(): - - current_version = get_current_version() - logger = logging.getLogger(__name__) - if current_version: - if pkg_resources.parse_version(__version__) <\ - pkg_resources.parse_version(current_version): - logger.warning("You are using conrad version %s; however," - " version %s is available.\n" - "You should consider upgrading via the " - "'pip install --upgrade conference-radar' command.\n", - __version__, current_version) - - if __name__ == "__main__": - - conrad_self_version_check() main() diff --git a/conrad/utils.py b/conrad/utils.py index cd4694b..bf84cd0 100644 --- a/conrad/utils.py +++ b/conrad/utils.py @@ -1,11 +1,107 @@ # -*- coding: utf-8 -*- -from .db import engine - +import os +import sys +import json +import logging +import datetime as dt +from setuptools.version import pkg_resources + +import requests import geopy.exc as geopyexceptions from geopy.geocoders import Nominatim from geopy.extra.rate_limiter import RateLimiter +from .db import engine +from . import __version__, CONRAD_HOME + + +SELFCHECK_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" + + +logger = logging.getLogger(__name__) + + +# https://github.com/pypa/pip/blob/master/src/pip/_internal/self_outdated_check.py +class SelfCheckState(object): + def __init__(self, cache_dir): + self.state = {} + self.statefile_path = os.path.join(cache_dir, "selfcheck.json") + + # Try to load the existing state + try: + with open(self.statefile_path, "r") as f: + self.state = json.load(f) + except (IOError, ValueError, KeyError, FileNotFoundError): + # Explicitly suppressing exceptions, since we don't want to + # error out if the cache file is invalid. + pass + + def save(self, pypi_version, current_time): + # If we do not have a path to cache in, don't bother saving. + if not self.statefile_path: + return + + state = { + "last_check": current_time.strftime(SELFCHECK_DATE_FMT), + "pypi_version": pypi_version, + } + + text = json.dumps(state, sort_keys=True, separators=(",", ":")) + + with open(self.statefile_path, "w") as f: + f.write(text) + + +def get_pypi_version(): + url = "https://pypi.org/pypi/conference-radar/json" + response = requests.get(url) + if response: + data = response.json() + pypi_version = data["info"]["version"] + return pypi_version + + +def conrad_self_version_check(): + pypi_version = None + + try: + state = SelfCheckState(cache_dir=CONRAD_HOME) + + current_time = dt.datetime.utcnow() + # Determine if we need to refresh the state + if "last_check" in state.state and "pypi_version" in state.state: + last_check = dt.datetime.strptime( + state.state["last_check"], + SELFCHECK_DATE_FMT + ) + if (current_time - last_check).total_seconds() < 7 * 24 * 60 * 60: + pypi_version = state.state["pypi_version"] + + # Refresh the version if we need to or just see if we need to warn + if pypi_version is None: + pypi_version = get_pypi_version() + + # Save that we've performed a check + state.save(pypi_version, current_time) + + conrad_version = pkg_resources.parse_version(__version__) + remote_version = pkg_resources.parse_version(pypi_version) + + if conrad_version < remote_version: + pip_cmd = "{} -m pip".format(sys.executable) + logger.warning( + f"You are using conrad version {__version__}; however," + f" version {pypi_version} is available.\n" + "You should consider upgrading with" + f" '{pip_cmd} install --upgrade conference-radar'." + ) + except Exception: + logger.debug( + "There was an error checking the latest version of conrad", + exc_info=True, + ) + def initialize_database(): from .models import Base diff --git a/setup.py b/setup.py index 3b94aac..5619a97 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ def setup_package(): packages=find_packages(exclude=("tests",)), install_requires=requires, extras_require={"dev": dev_requires}, - entry_points={"console_scripts": ["conrad = conrad.cli:cli"]}, + entry_points={"console_scripts": ["conrad = conrad.__main__:main"]}, classifiers=[ # Trove classifiers # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers