diff --git a/.travis.yml b/.travis.yml index f8480b79..b9f98bec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,55 +12,49 @@ matrix: language: ruby osx_image: xcode7.3 - os: linux - python: "3.4" + python: '3.4' services: - docker - if: NOT tag =~ .+ os: linux - python: "3.5" + python: '3.5' - if: NOT tag =~ .+ os: linux - python: "3.6" + python: '3.6' before_install: - source contrib/zclassic/travis/electrum_zclassic_version_env.sh - echo electrum-zclassic version is $ELECTRUM_ZCL_VERSION - mkdir -p build && cp contrib/zclassic/travis/* ./build/ -- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'osx' ]]; then - ./build/before_install-osx.sh; - fi -- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then - ./build/before_install-linux.sh; - fi -- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then - ./build/before_install-linux-apk.sh; +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'osx' ]]; then ./build/before_install-osx.sh; fi +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION + == '3.4' ]]; then ./build/before_install-linux.sh; fi +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION + == '3.5' ]]; then ./build/before_install-linux-apk.sh; fi install: -- if [[ -z $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]]; then - pip install tox; pip install tox-travis; - fi +- if [[ -z $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]]; then pip install tox; + pip install tox-travis; fi script: -- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'osx' ]]; then - ./build/travis-build-osx.sh ; - fi -- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then - ./build/travis-build-linux.sh; - fi -- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then - ./build/travis-build-linux-apk.sh; - fi +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'osx' ]]; then ./build/travis-build-osx.sh + ; fi +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION + == '3.4' ]]; then ./build/travis-build-linux.sh; fi +- if [[ -n $TRAVIS_TAG ]] && [[ $TRAVIS_OS_NAME == 'linux' ]] && [[ $TRAVIS_PYTHON_VERSION + == '3.5' ]]; then ./build/travis-build-linux-apk.sh; fi deploy: - provider: releases api_key: - secure: G+TcxPJSQQ2bTNhkTX4aofnsiNFrzbuFTGty/+jIKDb/IQ69etXS9Ulu8KGD71VjEdXugFWdus+2a8fFSCSg79+AvrSxKa1ztXQ2q6tmovRkUcnF5Bkbc+ORLm3+FMZhonvMg+MLnHS3hnvJL/CZU0Pn2dkfODn7/t+MsGs99MN0G44qimq+FCu+YHaKVcGgiTs1I6nextIH+lnPw5qE6VxTQKdFp4PTHqY1qZJWamReVvtyMnfGpa+QwcKf43dXzZrHMLfFprfzEi1DExrhRi0a8RZlFWmAtkwH9zzJXzqOEmivniLfeALJzWkBJG4I2Fu7QSQhvPllhnt5uGdV3pgmHZUxL1DZckrqVG5b6P/Cnmbu0hWXbkPpZ7sXQ4X7wGhAVgH2sRPF1SfE9XvqDsmKvpspdKGmI+9yKoaWekbt8igfJ8jRBK4yRJAt+F/waeXkj7HJhSPIYg9wNvYCnCmoih4brRcTE4nyJBo/ySY3DVocflS3QGoClOrBpwXGgzwaUzBamRhJeCUe9ockPJyUs9DkuBIdsPfhq0nZfZFMhNBtpzm1hPGE92NojUi+DcI12WqweUqDWZzY/02MmfHLeN6mGgjTWvgOwnq1fvc6s7sVy7nANtA6UseWF2KUBYfuMKAxTU4WadpZ102znz4XiL4B7TILKJMU+Ht+a+c= + secure: n0KT+T49e1mOIV64wpVmf4bYga4KArHQnY9ZQ3u2DImLRGmhMkpa/OC6/oboDdzdyC+IhpcdwX7uCu2lxlsFBfP2zyuprEQThxeW8gL6pFaTMoJJ201lNjppFmCpbS2VqxDJWIap3E+RHwoQZpo+b8Lt2xoOzB1VZFdxm4qVCb/I4jl5ZWouibYxMwb9IsqdakTK7ZTmCN+YMthsbgvRpjbb1s5vuE5I3AjVx3dFOR2YYvfdwjfknSY9Ej7xfUqmkraRdd4kRQrznVDdB5i9gvPTF1hxtGGusxsDHEYAe6pUdDKk6XZ6esM/MhZDHnxWMt0wUKNrdIIlL9gI767AHiP+VQ5SAfbbVZrkCVIQ4d8s7dH4AbFlW0dsj5OuLb00Mp99FPxYpmMkdz6agWQmFky83Hc++DiGaRGZQr3eQUnKUkuGsWjueXCh5AC4uYNNYnXlaz2mkrKxenWgXscAa7XlyVcdZMAilMeOVOjZdjkjhN0bPz905NOm0sCSkOiR6v0iJmFsw2KKZwGNBG/DQV4bBWzbEu3G5ehCP4WkbXh0Cfjxqi56LkZt4YXbkFIHY+qj0gE6tRQbc42lad8+aLGbi4mKnttCuLZbN70E+c1Y++VAaYAOCqF9VlDD5/4OIizeRYW9hC18wD0+T3GWK+mezpWKrWdkdIEEVvt1SyQ= file: - build/electrum-zclassic/dist/electrum-zclassic-$ELECTRUM_ZCL_VERSION-macosx.dmg on: repo: ZclassicCommunity/electrum-zclassic - tags: true + tags: false condition: "$TRAVIS_OS_NAME = osx" + draft: true - provider: releases api_key: - secure: G+TcxPJSQQ2bTNhkTX4aofnsiNFrzbuFTGty/+jIKDb/IQ69etXS9Ulu8KGD71VjEdXugFWdus+2a8fFSCSg79+AvrSxKa1ztXQ2q6tmovRkUcnF5Bkbc+ORLm3+FMZhonvMg+MLnHS3hnvJL/CZU0Pn2dkfODn7/t+MsGs99MN0G44qimq+FCu+YHaKVcGgiTs1I6nextIH+lnPw5qE6VxTQKdFp4PTHqY1qZJWamReVvtyMnfGpa+QwcKf43dXzZrHMLfFprfzEi1DExrhRi0a8RZlFWmAtkwH9zzJXzqOEmivniLfeALJzWkBJG4I2Fu7QSQhvPllhnt5uGdV3pgmHZUxL1DZckrqVG5b6P/Cnmbu0hWXbkPpZ7sXQ4X7wGhAVgH2sRPF1SfE9XvqDsmKvpspdKGmI+9yKoaWekbt8igfJ8jRBK4yRJAt+F/waeXkj7HJhSPIYg9wNvYCnCmoih4brRcTE4nyJBo/ySY3DVocflS3QGoClOrBpwXGgzwaUzBamRhJeCUe9ockPJyUs9DkuBIdsPfhq0nZfZFMhNBtpzm1hPGE92NojUi+DcI12WqweUqDWZzY/02MmfHLeN6mGgjTWvgOwnq1fvc6s7sVy7nANtA6UseWF2KUBYfuMKAxTU4WadpZ102znz4XiL4B7TILKJMU+Ht+a+c= + secure: n0KT+T49e1mOIV64wpVmf4bYga4KArHQnY9ZQ3u2DImLRGmhMkpa/OC6/oboDdzdyC+IhpcdwX7uCu2lxlsFBfP2zyuprEQThxeW8gL6pFaTMoJJ201lNjppFmCpbS2VqxDJWIap3E+RHwoQZpo+b8Lt2xoOzB1VZFdxm4qVCb/I4jl5ZWouibYxMwb9IsqdakTK7ZTmCN+YMthsbgvRpjbb1s5vuE5I3AjVx3dFOR2YYvfdwjfknSY9Ej7xfUqmkraRdd4kRQrznVDdB5i9gvPTF1hxtGGusxsDHEYAe6pUdDKk6XZ6esM/MhZDHnxWMt0wUKNrdIIlL9gI767AHiP+VQ5SAfbbVZrkCVIQ4d8s7dH4AbFlW0dsj5OuLb00Mp99FPxYpmMkdz6agWQmFky83Hc++DiGaRGZQr3eQUnKUkuGsWjueXCh5AC4uYNNYnXlaz2mkrKxenWgXscAa7XlyVcdZMAilMeOVOjZdjkjhN0bPz905NOm0sCSkOiR6v0iJmFsw2KKZwGNBG/DQV4bBWzbEu3G5ehCP4WkbXh0Cfjxqi56LkZt4YXbkFIHY+qj0gE6tRQbc42lad8+aLGbi4mKnttCuLZbN70E+c1Y++VAaYAOCqF9VlDD5/4OIizeRYW9hC18wD0+T3GWK+mezpWKrWdkdIEEVvt1SyQ= file: - build/electrum-zclassic/dist/Electrum-Zclassic-$ELECTRUM_ZCL_VERSION.tar.gz - build/electrum-zclassic/dist/electrum-zclassic-$ELECTRUM_ZCL_VERSION-setup-win32.exe @@ -68,5 +62,6 @@ deploy: - build/electrum-zclassic/bin/Electrum_Zclassic-$ELECTRUM_ZCL_APK_VERSION-release-unsigned.apk on: repo: ZclassicCommunity/electrum-zclassic - tags: true + tags: false condition: "$TRAVIS_OS_NAME = linux" + draft: true diff --git a/deterministic.spec b/deterministic.spec new file mode 100644 index 00000000..4116f230 --- /dev/null +++ b/deterministic.spec @@ -0,0 +1,160 @@ +# -*- mode: python -*- +import sys +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + + +for i, x in enumerate(sys.argv): + if x == '--name': + cmdline_name = sys.argv[i+1] + break +else: + raise Exception('no name') + +hiddenimports = collect_submodules('trezorlib') +hiddenimports += collect_submodules('btchip') +hiddenimports += collect_submodules('keepkeylib') +hiddenimports += collect_submodules('websocket') +hiddenimports += [ + 'lib', + 'lib.base_wizard', + 'lib.plot', + 'lib.qrscanner', + 'lib.websockets', + 'gui.qt', + + 'plugins', + + 'plugins.hw_wallet.qt', + + 'plugins.audio_modem.qt', + 'plugins.cosigner_pool.qt', + 'plugins.digitalbitbox.qt', + 'plugins.email_requests.qt', + 'plugins.keepkey.qt', + 'plugins.labels.qt', + 'plugins.trezor.qt', + 'plugins.ledger.qt', + 'plugins.virtualkeyboard.qt', +] + +datas = [ + ('lib/servers.json', 'electrum_zclassic'), + ('lib/servers_testnet.json', 'electrum_zclassic'), + ('lib/servers_regtest.json', 'electrum_zclassic'), + ('lib/currencies.json', 'electrum_zclassic'), + ('lib/locale', 'electrum_zclassic/locale'), + ('lib/wordlist', 'electrum_zclassic/wordlist'), + ('C:\\zbarw', '.'), +] +datas += collect_data_files('trezorlib') +datas += collect_data_files('btchip') +datas += collect_data_files('keepkeylib') + +binaries = [('C:/Python34/libusb-1.0.dll', '.')] + +# https://github.com/pyinstaller/pyinstaller/wiki/Recipe-remove-tkinter-tcl +sys.modules['FixTk'] = None +excludes = ['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'] +excludes += [ + 'PyQt5.QtCLucene', + 'PyQt5.Qt5CLucene', + 'PyQt5.QtDesigner', + 'PyQt5.QtDesignerComponents', + 'PyQt5.QtHelp', + 'PyQt5.QtLocation', + 'PyQt5.QtMultimedia', + 'PyQt5.QtMultimediaQuick_p', + 'PyQt5.QtMultimediaWidgets', + 'PyQt5.QtNetwork', + 'PyQt5.QtOpenGL', + 'PyQt5.QtPositioning', + 'PyQt5.QtPrintSupport', + 'PyQt5.QtQml', + 'PyQt5.QtQuick', + 'PyQt5.QtQuickParticles', + 'PyQt5.QtQuickWidgets', + 'PyQt5.QtSensors', + 'PyQt5.QtSerialPort', + 'PyQt5.QtSql', + 'PyQt5.Qt5Sql', + 'PyQt5.QtTest', + 'PyQt5.QtWebChannel', + 'PyQt5.QtWebKit', + 'PyQt5.QtWebKitWidgets', + 'PyQt5.QtWebSockets', + 'PyQt5.QtXml', + 'PyQt5.QtXmlPatterns', + 'PyQt5.QtWebProcess', + 'PyQt5.QtWinExtras', +] + +a = Analysis(['electrum-zclassic'], + pathex=['plugins'], + hiddenimports=hiddenimports, + datas=datas, + binaries=binaries, + excludes=excludes, + runtime_hooks=['pyi_runtimehook.py']) + +# http://stackoverflow.com/questions/19055089/ +for d in a.datas: + if 'pyconfig' in d[0]: + a.datas.remove(d) + break + +# Add TOC to electrum_zclassic, electrum_zclassic_gui, electrum_zclassic_plugins +for p in sorted(a.pure): + if p[0].startswith('lib') and p[2] == 'PYMODULE': + a.pure += [('electrum_zclassic%s' % p[0][3:] , p[1], p[2])] + if p[0].startswith('gui') and p[2] == 'PYMODULE': + a.pure += [('electrum_zclassic_gui%s' % p[0][3:] , p[1], p[2])] + if p[0].startswith('plugins') and p[2] == 'PYMODULE': + a.pure += [('electrum_zclassic_plugins%s' % p[0][7:] , p[1], p[2])] + +pyz = PYZ(a.pure) + +exe = EXE(pyz, + a.scripts, + exclude_binaries=True, + debug=False, + strip=False, + upx=False, + console=False, + icon='icons/electrum-zclassic.ico', + name=os.path.join('build\\pyi.win32\\electrum', cmdline_name)) + +# exe with console output +conexe = EXE(pyz, + a.scripts, + exclude_binaries=True, + debug=False, + strip=False, + upx=False, + console=True, + icon='icons/electrum-zclassic.ico', + name=os.path.join('build\\pyi.win32\\electrum', + 'console-%s' % cmdline_name)) + +# trezorctl separate executable +tctl_a = Analysis(['C:/Python34/Scripts/trezorctl'], + hiddenimports=['pkgutil'], + excludes=excludes, + runtime_hooks=['pyi_tctl_runtimehook.py']) + +tctl_pyz = PYZ(tctl_a.pure) + +tctl_exe = EXE(tctl_pyz, + tctl_a.scripts, + exclude_binaries=True, + debug=False, + strip=False, + upx=False, + console=True, + name=os.path.join('build\\pyi.win32\\electrum', 'trezorctl.exe')) + +coll = COLLECT(exe, conexe, tctl_exe, + a.binaries, + a.datas, + strip=False, + upx=False, + name=os.path.join('dist', 'electrum-zclassic')) diff --git a/pyi_runtimehook.py b/pyi_runtimehook.py new file mode 100644 index 00000000..f5e98ec4 --- /dev/null +++ b/pyi_runtimehook.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +"""PyInstaller runtime hook""" +import imp +import sys +import pkgutil + + +_old_find_module = imp.find_module +def _new_find_module(name, *args, **kwargs): + if name in ['lib', 'gui', 'plugins']: + return (None, name, ('', '', 5)) + else: + return _old_find_module(name, *args, **kwargs) +imp.find_module = _new_find_module + + +_old_load_module = imp.load_module +def _new_load_module(name, file, pathname, description): + if pathname in ['lib', 'gui', 'plugins']: + return __import__(name) + else: + return _old_load_module(name, file, pathname, description) +imp.load_module = _new_load_module + + +PLUGINS_PREFIX = 'electrum_zclassic_plugins' + +KEYSTORE_PLUGINS = [ + 'hw_wallet', + 'digitalbitbox', + 'keepkey', + 'ledger', + 'trezor', +] + +OTHER_PLUGINS= [ + 'audio_modem', + 'cosigner_pool', + 'email_requests', + 'labels', + 'virtualkeyboard', +] + +OTHER_PLUGINS = list(map(lambda p: '%s.%s' % (PLUGINS_PREFIX, p), OTHER_PLUGINS)) + +PLUGINS = KEYSTORE_PLUGINS + OTHER_PLUGINS + + +class PluginsImporter(object): + def find_module(self, name): + return self + + def load_module(self, name): + if name in KEYSTORE_PLUGINS: + return getattr(__import__('%s.%s' % (PLUGINS_PREFIX, name)), name) + elif name in OTHER_PLUGINS: + return getattr(__import__(name), name.split('.')[-1]) + elif name.endswith('.qt'): + split = name.split('.') + if split[0] != split[1]: + plugin_module = getattr(__import__(name), split[-2]) + return getattr(plugin_module, 'qt') + else: + path = '.'.join(split[1:]) + plugin_module = getattr(__import__(path), split[-2]) + return getattr(plugin_module, 'qt') + else: + raise Exception('Can not import %s' % name) + + +_old_find_loader = pkgutil.find_loader +def _new_find_loader(fullname): + if fullname.startswith('%s.' % PLUGINS_PREFIX): + return PluginsImporter() + else: + return _old_find_loader(fullname) +pkgutil.find_loader = _new_find_loader + + +_old_iter_modules = pkgutil.iter_modules +def _new_iter_modules(path=None, prefix=''): + if path and len(path) == 1 and path[0].endswith(PLUGINS_PREFIX): + for p in PLUGINS: + yield PluginsImporter(), p, True + else: + for loader, name, ispkg in _old_iter_modules(path, prefix): + yield loader, name, ispkg +pkgutil.iter_modules = _new_iter_modules diff --git a/pyi_tctl_runtimehook.py b/pyi_tctl_runtimehook.py new file mode 100644 index 00000000..942a5698 --- /dev/null +++ b/pyi_tctl_runtimehook.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +"""PyInstaller runtime hook for trezorctl""" +from sys import exit