move version checker to a thread (#421)

* move version checker to a thread

* add binary version via version.txt

* fix version comparison
This commit is contained in:
Stepan Snigirev 2020-09-21 18:12:03 +02:00 committed by GitHub
parent 5af4a809fa
commit bd89c8c882
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 140 additions and 47 deletions

1
.gitignore vendored
View file

@ -13,4 +13,5 @@ key.pem
*.dmg
pyinstaller/specterd
pyinstaller/release
pyinstaller/version.txt
.DS_Store

View file

@ -2,6 +2,7 @@
# pass version number as an argument
echo $1 > version.txt
pip install -e ..
pip install -r requirements.txt
rm -rf build/ dist/ release/

View file

@ -2,6 +2,7 @@
# pass version number as an argument
echo $1 > version.txt
pip install -e ..
pip install -r requirements.txt
rm -rf build/ dist/ release/

View file

@ -1,4 +1,5 @@
@ECHO OFF
echo %1 > version.txt
pip install -e ..
pip install -r requirements.txt
rmdir /s /q .\dist\

View file

@ -40,6 +40,7 @@ a = Analysis(['specter_desktop.py'],
('../src/cryptoadvance/specter/static', 'static'),
("./icons", "icons"),
(mnemonic_path, 'mnemonic/wordlist'),
("version.txt", "."),
],
hiddenimports=[
'pkg_resources.py2_warn',

View file

@ -25,6 +25,7 @@ a = Analysis(['specterd.py'],
datas=[('../src/cryptoadvance/specter/templates', 'templates'),
('../src/cryptoadvance/specter/static', 'static'),
(mnemonic_path, 'mnemonic/wordlist'),
("version.txt", "."),
],
hiddenimports=[
'pkg_resources.py2_warn',

View file

@ -16,8 +16,8 @@ from flask_login import login_required, login_user, logout_user, current_user
from flask_login.config import EXEMPT_METHODS
from .helpers import (alias, get_devices_with_keys_by_type,
get_loglevel, get_version_info, run_shell, set_loglevel,
from .helpers import (alias, get_devices_with_keys_by_type,
get_loglevel, run_shell, set_loglevel,
bcur2base64, get_txid, generate_mnemonic,
get_startblock_by_chain, fslock)
from .specter import Specter
@ -1484,9 +1484,6 @@ def notify_upgrade():
that there is an upgrade to specter.desktop
:return the current version
'''
version_info={}
version_info["current"], version_info["latest"], version_info["upgrade"] = get_version_info()
app.logger.info("Upgrade? {}".format(version_info["upgrade"]))
if version_info["upgrade"]:
flash("There is a new version available. Consider strongly to upgrade to the new version {} with \"pip3 install cryptoadvance.specter --upgrade\"".format(version_info["latest"]), "info")
return version_info["current"]
if app.specter.version.upgrade:
flash(f"Upgrade notification: new version {app.specter.version.latest} is available.", "info")
return app.specter.version.current

View file

@ -156,37 +156,6 @@ def get_loglevel(app):
return loglevels[app.logger.getEffectiveLevel()]
def get_version_info():
''' Returns a triple of the current version (of the pip-package cryptoadvance.specter and
the latest version and whether you should upgrade
'''
name="cryptoadvance.specter"
try:
# fail right away if it's a binary
if getattr(sys, 'frozen', False):
raise RuntimeError("Using frozen binary, verision unavailable")
latest_version = str(subprocess.run([sys.executable, '-m', 'pip', 'install', '{}==random'.format(name)], capture_output=True, text=True))
latest_version = latest_version[latest_version.find('(from versions:')+15:]
latest_version = latest_version[:latest_version.find(')')]
latest_version = latest_version.replace(' ','').split(',')[-1]
current_version = str(subprocess.run([sys.executable, '-m', 'pip', 'show', '{}'.format(name)], capture_output=True, text=True))
current_version = current_version[current_version.find('Version:')+8:]
current_version = current_version[:current_version.find('\\n')].replace(' ','')
# master?
if current_version == 'vx.y.z-get-replaced-by-release-script':
current_version = 'custom'
if re.search(r"v?([\d+]).([\d+]).([\d+]).*", current_version):
return current_version, latest_version, latest_version != current_version
return current_version, latest_version, False
except Exception as exc:
# if pip is not installed or we are using python3.6 or below
# we just don't show the version
logger.error(exc)
return "unknown", "unknown", False
def hwi_get_config(specter):
config = {
'whitelisted_domains': 'http://127.0.0.1:25441/'

View file

@ -12,6 +12,7 @@ from .specter import Specter
from .hwi_server import hwi_server
from .user import User
from .config import DATA_FOLDER
from .util.version import VersionChecker
logger = logging.getLogger()
@ -51,6 +52,11 @@ def init_app(app, hwibridge=False, specter=None):
app.logger.info("Initializing Specter")
specter = Specter(DATA_FOLDER)
# version checker
# checks for new versions once per hour
specter.version = VersionChecker()
specter.version.start()
login_manager = LoginManager()
login_manager.init_app(app) # Enable Login
login_manager.login_view = "login" # Enable redirects if unauthorized

View file

@ -6,7 +6,7 @@ import random
import time
import zipfile
from io import BytesIO
from .helpers import deep_update, clean_psbt, get_version_info
from .helpers import deep_update, clean_psbt
from .rpc import autodetect_rpc_confs, get_default_datadir, RpcError
from .rpc import BitcoinRPC
from .device_manager import DeviceManager
@ -470,9 +470,3 @@ class Specter:
def restore_from_backup(self):
pass
@property
def specter_version(self):
if not self._current_version:
self._current_version = get_version_info()[0]
return self._current_version

View file

@ -98,7 +98,7 @@
<p class="warning mobile-only">&#9432;<br><b>Specter "Watch Only" Mode.</b><br>You are using Specter from a small-screen device for which some functionalities, including sending funds and creating new wallets are not yet supported.</p>
<br>
<div class="footer">
<span>Specter Version: <strong>{{ specter.specter_version }}</strong></span>
<span>Specter Version: <strong>{{ specter.version.current }}</strong></span>
<a style="color: #fff; font-size: 1.1em; margin: 10px; text-align: center;" href="/about">
About Specter<br>
<img src="/static/img/icon.png" style="width: 35px;"/>

View file

@ -0,0 +1,121 @@
import subprocess
import sys
import logging
import re
import threading
import time
import os
import requests
logger = logging.getLogger(__name__)
class VersionChecker:
def __init__(self, name="cryptoadvance.specter"):
self.name = name
self.current = "unknown"
self.latest = "unknown"
self.upgrade = False
self.running = False
def start(self):
if not self.running:
self.running = True
self.thread = threading.Thread(target=self.loop)
self.thread.daemon = True
self.thread.start()
def stop(self):
self.running = False
@property
def info(self):
return {
"current": self.current,
"latest": self.latest,
"upgrade": self.upgrade,
}
def loop(self, dt=3600):
"""Checks for updates once per hour"""
while self.running:
self.current, self.latest, self.upgrade = self.get_version_info()
logger.info(f"version checked. upgrade: {self.upgrade}")
time.sleep(dt)
def get_binary_version(self):
"""
Get binary version: current, latest.
Fails if version.txt is not present.
Returns latest = "unknown" if fetch failed.
"""
version_file = "version.txt"
if getattr(sys, 'frozen', False):
version_file = os.path.join(sys._MEIPASS, 'version.txt')
with open(version_file) as f:
current = f.read().strip()
try:
releases = requests.get("https://api.github.com/repos/cryptoadvance/specter-desktop/releases").json()
latest = releases[0]["name"]
except:
latest = "unknown"
return current, latest
def get_pip_version(self):
latest = str(subprocess.run([
sys.executable, '-m', 'pip',
'install', f'{self.name}==random'],
capture_output=True, text=True))
latest = latest[latest.find(
'(from versions:')+15:]
latest = latest[:latest.find(')')]
latest = latest.replace(' ', '').split(',')[-1]
current = str(subprocess.run([
sys.executable, '-m', 'pip',
'show', f'{self.name}'],
capture_output=True, text=True))
current = current[current.find(
'Version:')+8:]
current = current[:current.find(
'\\n')].replace(' ', '')
# master?
if current == 'vx.y.z-get-replaced-by-release-script':
current = 'custom'
# no need to check upgrades
self.running = False
return current, latest
def get_version_info(self):
'''
Returns a triple of the current version
of the pip-package cryptoadvance.specter and
the latest version and whether you should upgrade.
'''
# check if we have version.txt file
# this is the case for binaries
current = "unknown"
latest = "unknown"
# check binary version
try:
current, latest = self.get_binary_version()
# if file not found
except FileNotFoundError as exc:
try:
current, latest = self.get_pip_version()
except Exception as exc:
logger.error(exc)
# other exceptions
except Exception as exc:
logger.error(exc)
# check that both current and latest versions match the pattern
if (re.search(r"v?([\d+]).([\d+]).([\d+]).*", current) and
re.search(r"v?([\d+]).([\d+]).([\d+]).*", latest)):
return (
current,
latest,
# check without leading v so v1.2.3 = 1.2.3
latest.replace("v","") != current.replace("v","")
)
return current, latest, False