Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move version checker to a thread #421

Merged
merged 7 commits into from
Sep 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ key.pem
*.dmg
pyinstaller/specterd
pyinstaller/release
pyinstaller/version.txt
.DS_Store
1 change: 1 addition & 0 deletions pyinstaller/build-osx.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down
1 change: 1 addition & 0 deletions pyinstaller/build-unix.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down
1 change: 1 addition & 0 deletions pyinstaller/build-win.bat
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@ECHO OFF
echo %1 > version.txt
pip install -e ..
pip install -r requirements.txt
rmdir /s /q .\dist\
Expand Down
1 change: 1 addition & 0 deletions pyinstaller/specter_desktop.spec
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
1 change: 1 addition & 0 deletions pyinstaller/specterd.spec
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
13 changes: 5 additions & 8 deletions src/cryptoadvance/specter/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
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
Expand Down Expand Up @@ -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
31 changes: 0 additions & 31 deletions src/cryptoadvance/specter/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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/'
Expand Down
6 changes: 6 additions & 0 deletions src/cryptoadvance/specter/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .hwi_server import hwi_server
from .user import User
from .config import DATA_FOLDER
from .util.version import VersionChecker

logger = logging.getLogger()

Expand Down Expand Up @@ -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
Expand Down
8 changes: 1 addition & 7 deletions src/cryptoadvance/specter/specter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
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
Expand Down Expand Up @@ -470,9 +470,3 @@ def specter_backup_file(self):
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

Original file line number Diff line number Diff line change
Expand Up @@ -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;"/>
Expand Down
121 changes: 121 additions & 0 deletions src/cryptoadvance/specter/util/version.py
Original file line number Diff line number Diff line change
@@ -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