openlp/openlp/core/version.py

208 lines
8.2 KiB
Python
Raw Normal View History

2017-06-17 08:51:01 +00:00
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
2017-12-29 09:15:48 +00:00
# Copyright (c) 2008-2018 OpenLP Developers #
2017-06-17 08:51:01 +00:00
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program 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 General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
2017-09-09 05:19:22 +00:00
The :mod:`openlp.core.version` module downloads the version details for OpenLP.
2017-06-17 08:51:01 +00:00
"""
2016-04-04 19:53:54 +00:00
import logging
import platform
import sys
from collections import OrderedDict
from datetime import date
2016-04-04 19:53:54 +00:00
from distutils.version import LooseVersion
2017-09-09 05:19:22 +00:00
import requests
2016-04-04 19:53:54 +00:00
from PyQt5 import QtCore
2017-10-07 07:05:07 +00:00
from openlp.core.common.applocation import AppLocation
from openlp.core.common.settings import Settings
from openlp.core.threading import ThreadWorker, run_thread
2016-07-01 21:17:20 +00:00
2018-10-02 04:39:42 +00:00
2016-04-04 19:53:54 +00:00
log = logging.getLogger(__name__)
APPLICATION_VERSION = {}
CONNECTION_TIMEOUT = 30
CONNECTION_RETRIES = 2
LIBRARIES = OrderedDict([
('Python', ('platform', 'python_version')),
('PyQt5', ('PyQt5.Qt', 'PYQT_VERSION_STR')),
('SQLAlchemy', ('sqlalchemy',)),
('Alembic', ('alembic',)),
('BeautifulSoup', ('bs4',)),
('lxml', ('lxml.etree',)),
('Chardet', ('chardet',)),
('PyEnchant', ('enchant',)),
('Mako', ('mako',)),
('pyICU', ('icu', 'VERSION')),
('VLC', ('openlp.core.ui.media.vlcplayer', 'VERSION')),
])
2016-04-04 19:53:54 +00:00
class VersionWorker(ThreadWorker):
2016-04-04 19:53:54 +00:00
"""
2017-09-09 05:19:22 +00:00
A worker class to fetch the version of OpenLP from the website. This is run from within a thread so that it
doesn't affect the loading time of OpenLP.
2016-04-04 19:53:54 +00:00
"""
2017-09-09 05:19:22 +00:00
new_version = QtCore.pyqtSignal(dict)
no_internet = QtCore.pyqtSignal()
def __init__(self, last_check_date, current_version):
2016-04-04 19:53:54 +00:00
"""
2017-09-09 05:19:22 +00:00
Constructor for the version check worker.
2016-04-04 19:53:54 +00:00
2017-09-09 05:19:22 +00:00
:param string last_check_date: The last day we checked for a new version of OpenLP
2016-04-04 19:53:54 +00:00
"""
2017-09-09 05:19:22 +00:00
log.debug('VersionWorker - Initialise')
super(VersionWorker, self).__init__(None)
self.last_check_date = last_check_date
self.current_version = current_version
2016-04-04 19:53:54 +00:00
2017-09-09 05:19:22 +00:00
def start(self):
2016-04-04 19:53:54 +00:00
"""
2017-09-09 05:19:22 +00:00
Check the latest version of OpenLP against the version file on the OpenLP site.
**Rules around versions and version files:**
* If a version number has a build (i.e. -bzr1234), then it is a nightly.
* If a version number's minor version is an odd number, it is a development release.
* If a version number's minor version is an even number, it is a stable release.
2016-04-04 19:53:54 +00:00
"""
2017-09-09 05:19:22 +00:00
log.debug('VersionWorker - Start')
download_url = 'https://www.openlp.org/files/version.txt'
if self.current_version['build']:
download_url = 'https://www.openlp.org/files/nightly_version.txt'
elif int(self.current_version['version'].split('.')[1]) % 2 != 0:
download_url = 'https://www.openlp.org/files/dev_version.txt'
2017-09-09 05:19:22 +00:00
headers = {
'User-Agent': 'OpenLP/{version} {system}/{release}; '.format(version=self.current_version['full'],
2017-09-09 05:19:22 +00:00
system=platform.system(),
release=platform.release())
}
remote_version = None
retries = 0
while retries < 3:
try:
response = requests.get(download_url, headers=headers)
2018-06-26 18:59:17 +00:00
if response.status_code == 200:
remote_version = response.text.strip()
2017-09-09 05:19:22 +00:00
log.debug('New version found: %s', remote_version)
break
except OSError:
2017-09-09 05:19:22 +00:00
log.exception('Unable to connect to OpenLP server to download version file')
retries += 1
else:
self.no_internet.emit()
if remote_version and LooseVersion(remote_version) > LooseVersion(self.current_version['full']):
2017-09-09 05:19:22 +00:00
self.new_version.emit(remote_version)
self.quit.emit()
def update_check_date():
"""
Save when we last checked for an update
"""
Settings().setValue('core/last version test', date.today().strftime('%Y-%m-%d'))
def check_for_update(main_window):
2017-09-09 05:19:22 +00:00
"""
Run a thread to download and check the version of OpenLP
:param MainWindow main_window: The OpenLP main window.
2017-09-09 05:19:22 +00:00
"""
last_check_date = Settings().value('core/last version test')
if date.today().strftime('%Y-%m-%d') <= last_check_date:
2017-09-09 05:19:22 +00:00
log.debug('Version check skipped, last checked today')
return
worker = VersionWorker(last_check_date, get_version())
worker.new_version.connect(main_window.on_new_version)
worker.quit.connect(update_check_date)
2017-09-09 05:19:22 +00:00
# TODO: Use this to figure out if there's an Internet connection?
# worker.no_internet.connect(parent.on_no_internet)
2017-12-17 06:54:21 +00:00
run_thread(worker, 'version')
2017-09-09 05:19:22 +00:00
def get_version():
2016-04-04 19:53:54 +00:00
"""
Returns the application version of the running instance of OpenLP::
{'full': '1.9.4-bzr1249', 'version': '1.9.4', 'build': 'bzr1249'}
"""
global APPLICATION_VERSION
if APPLICATION_VERSION:
return APPLICATION_VERSION
file_path = AppLocation.get_directory(AppLocation.VersionDir) / '.version'
try:
full_version = file_path.read_text().rstrip()
except OSError:
log.exception('Error in version file.')
2018-04-06 19:55:08 +00:00
full_version = '0.0.0'
2016-04-04 19:53:54 +00:00
bits = full_version.split('-')
APPLICATION_VERSION = {
'full': full_version,
'version': bits[0],
'build': bits[1] if len(bits) > 1 else None
}
if APPLICATION_VERSION['build']:
log.info('OpenLP version {version} build {build}'.format(version=APPLICATION_VERSION['version'],
build=APPLICATION_VERSION['build']))
2016-04-04 19:53:54 +00:00
else:
log.info('OpenLP version {version}'.format(version=APPLICATION_VERSION['version']))
2016-04-04 19:53:54 +00:00
return APPLICATION_VERSION
def _get_lib_version(library, version_attr='__version__'):
"""
Import a library and return the value of its version attribute.
:param str library: The name of the library to import
:param str version_attr: The name of the attribute containing the version number. Defaults to '__version__'
:returns str: The version number as a string
"""
if library not in sys.modules:
try:
__import__(library)
except ImportError:
return None
if not hasattr(sys.modules[library], version_attr):
return 'OK'
else:
attr = getattr(sys.modules[library], version_attr)
if callable(attr):
return str(attr())
else:
return str(attr)
def get_library_versions():
"""
Read and return the versions of the libraries we use.
:returns OrderedDict: A dictionary of {'library': 'version'}
"""
library_versions = OrderedDict([(library, _get_lib_version(*args)) for library, args in LIBRARIES.items()])
# Just update the dict for display purposes, changing the None to a '-'
for library, version in library_versions:
if version is None:
library_versions[library] = '-'
return library_versions