9
from datetime import datetime
10
from distutils.version import LooseVersion
11
from subprocess import Popen, PIPE
13
from openlp.core.common import AppLocation, Settings
15
from PyQt5 import QtCore
17
log = logging.getLogger(__name__)
19
APPLICATION_VERSION = {}
20
CONNECTION_TIMEOUT = 30
21
CONNECTION_RETRIES = 2
24
class VersionThread(QtCore.QThread):
26
A special Qt thread class to fetch the version of OpenLP from the website.
27
This is threaded so that it doesn't affect the loading time of OpenLP.
29
def __init__(self, main_window):
31
Constructor for the thread class.
33
:param main_window: The main window Object.
35
log.debug("VersionThread - Initialise")
36
super(VersionThread, self).__init__(None)
37
self.main_window = main_window
44
log.debug('Version thread - run')
45
app_version = get_application_version()
46
version = check_latest_version(app_version)
47
log.debug("Versions %s and %s " % (LooseVersion(str(version)), LooseVersion(str(app_version['full']))))
48
if LooseVersion(str(version)) > LooseVersion(str(app_version['full'])):
49
self.main_window.openlp_version_check.emit('%s' % version)
52
def get_application_version():
54
Returns the application version of the running instance of OpenLP::
56
{'full': '1.9.4-bzr1249', 'version': '1.9.4', 'build': 'bzr1249'}
58
global APPLICATION_VERSION
59
if APPLICATION_VERSION:
60
return APPLICATION_VERSION
61
if '--dev-version' in sys.argv or '-d' in sys.argv:
62
# NOTE: The following code is a duplicate of the code in setup.py. Any fix applied here should also be applied
65
# Get the revision of this tree.
66
bzr = Popen(('bzr', 'revno'), stdout=PIPE)
67
tree_revision, error = bzr.communicate()
68
tree_revision = tree_revision.decode()
71
raise Exception('Error running bzr log')
74
bzr = Popen(('bzr', 'tags'), stdout=PIPE)
75
output, error = bzr.communicate()
78
raise Exception('Error running bzr tags')
79
tags = list(map(bytes.decode, output.splitlines()))
84
# Remove any tag that has "?" as revision number. A "?" as revision number indicates, that this tag is from
86
tags = [tag for tag in tags if tag.split()[-1].strip() != '?']
87
# Get the last tag and split it in a revision and tag name.
88
tag_version, tag_revision = tags[-1].split()
89
# If they are equal, then this tree is tarball with the source for the release. We do not want the revision
90
# number in the full version.
91
if tree_revision == tag_revision:
92
full_version = tag_version.strip()
94
full_version = '%s-bzr%s' % (tag_version.strip(), tree_revision.strip())
96
# We're not running the development version, let's use the file.
97
file_path = AppLocation.get_directory(AppLocation.VersionDir)
98
file_path = os.path.join(file_path, '.version')
101
version_file = open(file_path, 'r')
102
full_version = str(version_file.read()).rstrip()
104
log.exception('Error in version file.')
105
full_version = '0.0.0-bzr000'
109
bits = full_version.split('-')
110
APPLICATION_VERSION = {
111
'full': full_version,
113
'build': bits[1] if len(bits) > 1 else None
115
if APPLICATION_VERSION['build']:
116
log.info('Openlp version %s build %s', APPLICATION_VERSION['version'], APPLICATION_VERSION['build'])
118
log.info('Openlp version %s' % APPLICATION_VERSION['version'])
119
return APPLICATION_VERSION
122
def check_latest_version(current_version):
124
Check the latest version of OpenLP against the version file on the OpenLP
127
**Rules around versions and version files:**
129
* If a version number has a build (i.e. -bzr1234), then it is a nightly.
130
* If a version number's minor version is an odd number, it is a development release.
131
* If a version number's minor version is an even number, it is a stable release.
133
:param current_version: The current version of OpenLP.
135
version_string = current_version['full']
136
# set to prod in the distribution config file.
137
settings = Settings()
138
settings.beginGroup('core')
139
last_test = settings.value('last version test')
140
this_test = str(datetime.now().date())
141
settings.setValue('last version test', this_test)
143
if last_test != this_test:
144
if current_version['build']:
145
req = urllib.request.Request('http://www.openlp.org/files/nightly_version.txt')
147
version_parts = current_version['version'].split('.')
148
if int(version_parts[1]) % 2 != 0:
149
req = urllib.request.Request('http://www.openlp.org/files/dev_version.txt')
151
req = urllib.request.Request('http://www.openlp.org/files/version.txt')
152
req.add_header('User-Agent', 'OpenLP/%s %s/%s; ' % (current_version['full'], platform.system(),
154
remote_version = None
158
remote_version = str(urllib.request.urlopen(req, None,
159
timeout=CONNECTION_TIMEOUT).read().decode()).strip()
160
except (urllib.error.URLError, ConnectionError):
161
if retries > CONNECTION_RETRIES:
162
log.exception('Failed to download the latest OpenLP version file')
169
version_string = remote_version
170
return version_string