This file is indexed.

/usr/lib/python3/dist-packages/glances/outdated.py is in glances 2.7.1.1-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# -*- coding: utf-8 -*-
#
# This file is part of Glances.
#
# Copyright (C) 2016 Nicolargo <nicolas@nicolargo.com>
#
# Glances is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Glances is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Manage Glances update."""

from datetime import datetime, timedelta
from distutils.version import LooseVersion
import threading
import json
import pickle
import os
try:
    import requests
except ImportError:
    outdated_tag = False
else:
    outdated_tag = True

from glances import __version__, __appname__
from glances.globals import BSD, LINUX, OSX, WINDOWS
from glances.logger import logger


class Outdated(object):

    """
    This class aims at providing methods to warn the user when a new Glances
    version is available on the Pypi repository (https://pypi.python.org/pypi/Glances/).
    """

    PYPI_API_URL = 'https://pypi.python.org/pypi/Glances/json'
    max_refresh_date = timedelta(days=7)

    def __init__(self, args, config):
        """Init the Outdated class"""
        self.args = args
        self.config = config

        # Set default value...
        self.data = {
            u'installed_version': __version__,
            u'latest_version': '0.0',
            u'refresh_date': datetime.now()
        }
        # Read the configuration file
        self.load_config(config)
        logger.debug("Check Glances version up-to-date: {}".format(not self.args.disable_check_update))

        # And update !
        self.get_pypi_version()

    def load_config(self, config):
        """Load outdated parameter in the global section of the configuration file."""

        global_section = 'global'
        if (hasattr(config, 'has_section') and
                config.has_section(global_section)):
            self.args.disable_check_update = config.get_value(global_section, 'check_update').lower() == 'false'
        else:
            logger.debug("Cannot find section {} in the configuration file".format(global_section))
            return False

        return True

    def installed_version(self):
        return self.data['installed_version']

    def latest_version(self):
        return self.data['latest_version']

    def refresh_date(self):
        return self.data['refresh_date']

    def get_pypi_version(self):
        """Wrapper to get the latest Pypi version (async)
        The data are stored in a cached file
        Only update online once a week
        """
        if not outdated_tag or self.args.disable_check_update:
            return

        # If the cached file exist, read-it
        cached_data = self._load_cache()

        if cached_data == {}:
            # Update needed
            # Update and save the cache
            thread = threading.Thread(target=self._update_pypi_version)
            thread.start()
        else:
            # Update not needed
            self.data['latest_version'] = cached_data['latest_version']
            logger.debug("Get the Glances version from the cache file")

    def is_outdated(self):
        """Return True if a new version is available"""
        if self.args.disable_check_update:
            # Check is disabled by configuration
            return False

        if not outdated_tag:
            logger.debug("Python Request lib is not installed. Can not get last Glances version on Pypi.")
            return False

        logger.debug("Check Glances version (installed: {} / latest: {})".format(self.installed_version(), self.latest_version()))
        return LooseVersion(self.latest_version()) > LooseVersion(self.installed_version())

    def _load_cache(self):
        """Load cache file and return cached data"""
        # If the cached file exist, read-it
        cached_data = {}
        try:
            with open(os.path.join(self._cache_path(), 'glances-version.db'), 'rb') as f:
                cached_data = pickle.load(f)
        except Exception as e:
            logger.debug("Cannot read the version cache file ({})".format(e))
        else:
            logger.debug("Read the version cache file")
            if cached_data['installed_version'] != self.installed_version() or \
               datetime.now() - cached_data['refresh_date'] > self.max_refresh_date:
                # Reset the cache if:
                # - the installed version is different
                # - the refresh_date is > max_refresh_date
                cached_data = {}
        return cached_data

    def _save_cache(self):
        """Save data to a file"""
        # If the cached file exist, read-it
        try:
            with open(os.path.join(self._cache_path(), 'glances-version.db'), 'wb') as f:
                pickle.dump(self.data, f)
        except IOError:
            return False
        return True

    def _cache_path(self):
        """Return the cached file path"""
        if LINUX or BSD:
            return os.path.join(os.environ.get('XDG_CONFIG_HOME') or
                                os.path.expanduser('~/.config'),
                                __appname__)
        elif OSX:
            return os.path.join(os.path.expanduser('~/Library/Application Support/'),
                                __appname__)
        elif WINDOWS:
            return os.path.join(os.environ.get('APPDATA'), __appname__)

    def _update_pypi_version(self):
        """Get the latest Pypi version (as a string) via the Restful JSON API"""
        # Get the Nginx status
        logger.debug("Get latest Glances version from the PyPI RESTful API ({})".format(self.PYPI_API_URL))

        # Update the current time
        self.data[u'refresh_date'] = datetime.now()

        try:
            res = requests.get(self.PYPI_API_URL)
        except Exception as e:
            logger.debug("Cannot get the Glances version from the PyPI RESTful API ({})".format(e))
        else:
            if res.ok:
                # Update data
                self.data[u'latest_version'] = json.loads(res.text)['info']['version']
                logger.debug("Save Glances version to the cache file")
            else:
                logger.debug("Cannot get the Glances version from the PyPI RESTful API ({})".format(res.reason))

        # Save result to the cache file
        # Note: also saved if the Glances Pypi version can not be grabed
        self._save_cache()

        return self.data