flake8: depends
This commit is contained in:
parent
b27cc071a2
commit
701521c55a
217
src/depends.py
217
src/depends.py
|
@ -1,16 +1,18 @@
|
|||
#! python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import pyelliptic.openssl
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# Only really old versions of Python don't have sys.hexversion. We don't
|
||||
# support them. The logging module was introduced in Python 2.3
|
||||
if not hasattr(sys, 'hexversion') or sys.hexversion < 0x20300F0:
|
||||
sys.stdout.write('Python version: ' + sys.version)
|
||||
sys.stdout.write('PyBitmessage requires Python 2.7.3 or greater (but not Python 3)')
|
||||
sys.exit()
|
||||
sys.exit(
|
||||
'Python version: %s\n'
|
||||
'PyBitmessage requires Python 2.7.3 or greater (but not Python 3)'
|
||||
% sys.version
|
||||
)
|
||||
|
||||
# We can now use logging so set up a simple configuration
|
||||
import logging
|
||||
|
@ -32,22 +34,28 @@ def check_hashlib():
|
|||
"""Do hashlib check.
|
||||
|
||||
The hashlib module check with version as if it included or not
|
||||
in The Python Standard library , its a module containing an
|
||||
in The Python Standard library, it's a module containing an
|
||||
interface to the most popular hashing algorithms. hashlib
|
||||
implements some of the algorithms, however if OpenSSL
|
||||
installed, hashlib is able to use this algorithms as well.
|
||||
"""
|
||||
if sys.hexversion < 0x020500F0:
|
||||
logger.error('The hashlib module is not included in this version of Python.')
|
||||
logger.error(
|
||||
'The hashlib module is not included in this version of Python.')
|
||||
return False
|
||||
import hashlib
|
||||
if '_hashlib' not in hashlib.__dict__:
|
||||
logger.error('The RIPEMD-160 hash algorithm is not available. The hashlib module is not linked against OpenSSL.')
|
||||
logger.error(
|
||||
'The RIPEMD-160 hash algorithm is not available.'
|
||||
' The hashlib module is not linked against OpenSSL.')
|
||||
return False
|
||||
try:
|
||||
hashlib.new('ripemd160')
|
||||
except ValueError:
|
||||
logger.error('The RIPEMD-160 hash algorithm is not available. The hashlib module utilizes an OpenSSL library with RIPEMD disabled.')
|
||||
logger.error(
|
||||
'The RIPEMD-160 hash algorithm is not available.'
|
||||
' The hashlib module utilizes an OpenSSL library with'
|
||||
' RIPEMD disabled.')
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -59,9 +67,11 @@ def check_sqlite():
|
|||
support in python version for specifieed platform.
|
||||
"""
|
||||
if sys.hexversion < 0x020500F0:
|
||||
logger.error('The sqlite3 module is not included in this version of Python.')
|
||||
logger.error(
|
||||
'The sqlite3 module is not included in this version of Python.')
|
||||
if sys.platform.startswith('freebsd'):
|
||||
logger.error('On FreeBSD, try running "pkg install py27-sqlite3" as root.')
|
||||
logger.error(
|
||||
'On FreeBSD, try running "pkg install py27-sqlite3" as root.')
|
||||
return False
|
||||
try:
|
||||
import sqlite3
|
||||
|
@ -69,25 +79,37 @@ def check_sqlite():
|
|||
logger.error('The sqlite3 module is not available')
|
||||
return False
|
||||
|
||||
logger.info('sqlite3 Module Version: ' + sqlite3.version)
|
||||
logger.info('SQLite Library Version: ' + sqlite3.sqlite_version)
|
||||
logger.info('sqlite3 Module Version: %s', sqlite3.version)
|
||||
logger.info('SQLite Library Version: %s', sqlite3.sqlite_version)
|
||||
# sqlite_version_number formula: https://sqlite.org/c3ref/c_source_id.html
|
||||
sqlite_version_number = sqlite3.sqlite_version_info[0] * 1000000 + sqlite3.sqlite_version_info[1] * 1000 + sqlite3.sqlite_version_info[2]
|
||||
sqlite_version_number = (
|
||||
sqlite3.sqlite_version_info[0] * 1000000
|
||||
+ sqlite3.sqlite_version_info[1] * 1000
|
||||
+ sqlite3.sqlite_version_info[2]
|
||||
)
|
||||
|
||||
conn = None
|
||||
try:
|
||||
try:
|
||||
conn = sqlite3.connect(':memory:')
|
||||
if sqlite_version_number >= 3006018:
|
||||
sqlite_source_id = conn.execute('SELECT sqlite_source_id();').fetchone()[0]
|
||||
logger.info('SQLite Library Source ID: ' + sqlite_source_id)
|
||||
sqlite_source_id = conn.execute(
|
||||
'SELECT sqlite_source_id();'
|
||||
).fetchone()[0]
|
||||
logger.info('SQLite Library Source ID: %s', sqlite_source_id)
|
||||
if sqlite_version_number >= 3006023:
|
||||
compile_options = ', '.join(map(lambda row: row[0], conn.execute('PRAGMA compile_options;')))
|
||||
logger.info('SQLite Library Compile Options: ' + compile_options)
|
||||
#There is no specific version requirement as yet, so we just use the
|
||||
#first version that was included with Python.
|
||||
compile_options = ', '.join(map(
|
||||
lambda row: row[0],
|
||||
conn.execute('PRAGMA compile_options;')
|
||||
))
|
||||
logger.info(
|
||||
'SQLite Library Compile Options: %s', compile_options)
|
||||
# There is no specific version requirement as yet, so we just
|
||||
# use the first version that was included with Python.
|
||||
if sqlite_version_number < 3000008:
|
||||
logger.error('This version of SQLite is too old. PyBitmessage requires SQLite 3.0.8 or later')
|
||||
logger.error(
|
||||
'This version of SQLite is too old.'
|
||||
' PyBitmessage requires SQLite 3.0.8 or later')
|
||||
return False
|
||||
return True
|
||||
except sqlite3.Error:
|
||||
|
@ -97,6 +119,7 @@ def check_sqlite():
|
|||
if conn:
|
||||
conn.close()
|
||||
|
||||
|
||||
def check_openssl():
|
||||
"""Do openssl dependency check.
|
||||
|
||||
|
@ -106,7 +129,8 @@ def check_openssl():
|
|||
try:
|
||||
import ctypes
|
||||
except ImportError:
|
||||
logger.error('Unable to check OpenSSL. The ctypes module is not available.')
|
||||
logger.error(
|
||||
'Unable to check OpenSSL. The ctypes module is not available.')
|
||||
return False
|
||||
|
||||
# We need to emulate the way PyElliptic searches for OpenSSL.
|
||||
|
@ -140,33 +164,42 @@ def check_openssl():
|
|||
cflags_regex = re.compile(r'(?:OPENSSL_NO_)(AES|EC|ECDH|ECDSA)(?!\w)')
|
||||
|
||||
for path in paths:
|
||||
logger.info('Checking OpenSSL at ' + path)
|
||||
logger.info('Checking OpenSSL at %s', path)
|
||||
try:
|
||||
library = ctypes.CDLL(path)
|
||||
except OSError:
|
||||
continue
|
||||
logger.info('OpenSSL Name: ' + library._name)
|
||||
logger.info('OpenSSL Name: %s', library._name)
|
||||
try:
|
||||
openssl_version, openssl_hexversion, openssl_cflags = pyelliptic.openssl.get_version(library)
|
||||
openssl_version, openssl_hexversion, openssl_cflags = \
|
||||
pyelliptic.openssl.get_version(library)
|
||||
except AttributeError: # sphinx chokes
|
||||
return True
|
||||
if not openssl_version:
|
||||
logger.error('Cannot determine version of this OpenSSL library.')
|
||||
return False
|
||||
logger.info('OpenSSL Version: ' + openssl_version)
|
||||
logger.info('OpenSSL Compile Options: ' + openssl_cflags)
|
||||
logger.info('OpenSSL Version: %s', openssl_version)
|
||||
logger.info('OpenSSL Compile Options: %s', openssl_cflags)
|
||||
# PyElliptic uses EVP_CIPHER_CTX_new and EVP_CIPHER_CTX_free which were
|
||||
# introduced in 0.9.8b.
|
||||
if openssl_hexversion < 0x90802F:
|
||||
logger.error('This OpenSSL library is too old. PyBitmessage requires OpenSSL 0.9.8b or later with AES, Elliptic Curves (EC), ECDH, and ECDSA enabled.')
|
||||
logger.error(
|
||||
'This OpenSSL library is too old. PyBitmessage requires'
|
||||
' OpenSSL 0.9.8b or later with AES, Elliptic Curves (EC),'
|
||||
' ECDH, and ECDSA enabled.')
|
||||
return False
|
||||
matches = cflags_regex.findall(openssl_cflags)
|
||||
if len(matches) > 0:
|
||||
logger.error('This OpenSSL library is missing the following required features: ' + ', '.join(matches) + '. PyBitmessage requires OpenSSL 0.9.8b or later with AES, Elliptic Curves (EC), ECDH, and ECDSA enabled.')
|
||||
logger.error(
|
||||
'This OpenSSL library is missing the following required'
|
||||
' features: %s. PyBitmessage requires OpenSSL 0.9.8b'
|
||||
' or later with AES, Elliptic Curves (EC), ECDH,'
|
||||
' and ECDSA enabled.', ', '.join(matches))
|
||||
return False
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# TODO: The minimum versions of pythondialog and dialog need to be determined
|
||||
def check_curses():
|
||||
"""Do curses dependency check.
|
||||
|
@ -176,33 +209,42 @@ def check_curses():
|
|||
utility.
|
||||
"""
|
||||
if sys.hexversion < 0x20600F0:
|
||||
logger.error('The curses interface requires the pythondialog package and the dialog utility.')
|
||||
logger.error(
|
||||
'The curses interface requires the pythondialog package and'
|
||||
' the dialog utility.')
|
||||
return False
|
||||
try:
|
||||
import curses
|
||||
except ImportError:
|
||||
logger.error('The curses interface can not be used. The curses module is not available.')
|
||||
logger.error(
|
||||
'The curses interface can not be used. The curses module'
|
||||
' is not available.')
|
||||
return False
|
||||
logger.info('curses Module Version: ' + curses.version)
|
||||
logger.info('curses Module Version: %s', curses.version)
|
||||
try:
|
||||
import dialog
|
||||
except ImportError:
|
||||
logger.error('The curses interface can not be used. The pythondialog package is not available.')
|
||||
logger.error(
|
||||
'The curses interface can not be used. The pythondialog'
|
||||
' package is not available.')
|
||||
return False
|
||||
try:
|
||||
subprocess.check_call('which dialog')
|
||||
except subprocess.CalledProcessError:
|
||||
logger.error('Curses requires the `dialog` command to be installed as well as the python library.')
|
||||
logger.error(
|
||||
'Curses requires the `dialog` command to be installed as well as'
|
||||
' the python library.')
|
||||
return False
|
||||
|
||||
logger.info('pythondialog Package Version: ' + dialog.__version__)
|
||||
logger.info('pythondialog Package Version: %s', dialog.__version__)
|
||||
dialog_util_version = dialog.Dialog().cached_backend_version
|
||||
# The pythondialog author does not like Python2 str, so we have to use
|
||||
#unicode for just the version otherwise we get the repr form which includes
|
||||
#the module and class names along with the actual version.
|
||||
logger.info('dialog Utility Version' + unicode(dialog_util_version))
|
||||
# unicode for just the version otherwise we get the repr form which
|
||||
# includes the module and class names along with the actual version.
|
||||
logger.info('dialog Utility Version %s', unicode(dialog_util_version))
|
||||
return True
|
||||
|
||||
|
||||
def check_pyqt():
|
||||
"""Do pyqt dependency check.
|
||||
|
||||
|
@ -212,37 +254,56 @@ def check_pyqt():
|
|||
try:
|
||||
import PyQt4.QtCore
|
||||
except ImportError:
|
||||
logger.error('The PyQt4 package is not available. PyBitmessage requires PyQt 4.8 or later and Qt 4.7 or later.')
|
||||
logger.error(
|
||||
'The PyQt4 package is not available. PyBitmessage requires'
|
||||
' PyQt 4.8 or later and Qt 4.7 or later.')
|
||||
if sys.platform.startswith('openbsd'):
|
||||
logger.error('On OpenBSD, try running "pkg_add py-qt4" as root.')
|
||||
elif sys.platform.startswith('freebsd'):
|
||||
logger.error('On FreeBSD, try running "pkg install py27-qt4" as root.')
|
||||
logger.error(
|
||||
'On FreeBSD, try running "pkg install py27-qt4" as root.')
|
||||
elif os.path.isfile("/etc/os-release"):
|
||||
with open("/etc/os-release", 'rt') as osRelease:
|
||||
for line in osRelease:
|
||||
if line.startswith("NAME="):
|
||||
if "fedora" in line.lower():
|
||||
logger.error('On Fedora, try running "dnf install PyQt4" as root.')
|
||||
logger.error(
|
||||
'On Fedora, try running'
|
||||
' "dnf install PyQt4" as root.')
|
||||
elif "opensuse" in line.lower():
|
||||
logger.error('On openSUSE, try running "zypper install python-qt" as root.')
|
||||
logger.error(
|
||||
'On openSUSE, try running'
|
||||
' "zypper install python-qt" as root.')
|
||||
elif "ubuntu" in line.lower():
|
||||
logger.error('On Ubuntu, try running "apt-get install python-qt4" as root.')
|
||||
logger.error(
|
||||
'On Ubuntu, try running'
|
||||
' "apt-get install python-qt4" as root.')
|
||||
elif "debian" in line.lower():
|
||||
logger.error('On Debian, try running "apt-get install python-qt4" as root.')
|
||||
logger.error(
|
||||
'On Debian, try running'
|
||||
' "apt-get install python-qt4" as root.')
|
||||
else:
|
||||
logger.error('If your package manager does not have this package, try running "pip install PyQt4".')
|
||||
logger.error(
|
||||
'If your package manager does not have'
|
||||
' this package, try running'
|
||||
' "pip install PyQt4".')
|
||||
return False
|
||||
logger.info('PyQt Version: ' + PyQt4.QtCore.PYQT_VERSION_STR)
|
||||
logger.info('Qt Version: ' + PyQt4.QtCore.QT_VERSION_STR)
|
||||
logger.info('PyQt Version: %s', PyQt4.QtCore.PYQT_VERSION_STR)
|
||||
logger.info('Qt Version: %s', PyQt4.QtCore.QT_VERSION_STR)
|
||||
passed = True
|
||||
if PyQt4.QtCore.PYQT_VERSION < 0x40800:
|
||||
logger.error('This version of PyQt is too old. PyBitmessage requries PyQt 4.8 or later.')
|
||||
logger.error(
|
||||
'This version of PyQt is too old. PyBitmessage requries'
|
||||
' PyQt 4.8 or later.')
|
||||
passed = False
|
||||
if PyQt4.QtCore.QT_VERSION < 0x40700:
|
||||
logger.error('This version of Qt is too old. PyBitmessage requries Qt 4.7 or later.')
|
||||
logger.error(
|
||||
'This version of Qt is too old. PyBitmessage requries'
|
||||
' Qt 4.7 or later.')
|
||||
passed = False
|
||||
return passed
|
||||
|
||||
|
||||
def check_msgpack():
|
||||
"""Do sgpack module check.
|
||||
|
||||
|
@ -256,26 +317,42 @@ def check_msgpack():
|
|||
'The msgpack package is not available.'
|
||||
'It is highly recommended for messages coding.')
|
||||
if sys.platform.startswith('openbsd'):
|
||||
logger.error('On OpenBSD, try running "pkg_add py-msgpack" as root.')
|
||||
logger.error(
|
||||
'On OpenBSD, try running "pkg_add py-msgpack" as root.')
|
||||
elif sys.platform.startswith('freebsd'):
|
||||
logger.error('On FreeBSD, try running "pkg install py27-msgpack-python" as root.')
|
||||
logger.error(
|
||||
'On FreeBSD, try running "pkg install py27-msgpack-python"'
|
||||
' as root.')
|
||||
elif os.path.isfile("/etc/os-release"):
|
||||
with open("/etc/os-release", 'rt') as osRelease:
|
||||
for line in osRelease:
|
||||
if line.startswith("NAME="):
|
||||
if "fedora" in line.lower():
|
||||
logger.error('On Fedora, try running "dnf install python2-msgpack" as root.')
|
||||
logger.error(
|
||||
'On Fedora, try running'
|
||||
' "dnf install python2-msgpack" as root.')
|
||||
elif "opensuse" in line.lower():
|
||||
logger.error('On openSUSE, try running "zypper install python-msgpack-python" as root.')
|
||||
logger.error(
|
||||
'On openSUSE, try running'
|
||||
' "zypper install python-msgpack-python"'
|
||||
' as root.')
|
||||
elif "ubuntu" in line.lower():
|
||||
logger.error('On Ubuntu, try running "apt-get install python-msgpack" as root.')
|
||||
logger.error(
|
||||
'On Ubuntu, try running'
|
||||
' "apt-get install python-msgpack" as root.')
|
||||
elif "debian" in line.lower():
|
||||
logger.error('On Debian, try running "apt-get install python-msgpack" as root.')
|
||||
logger.error(
|
||||
'On Debian, try running'
|
||||
' "apt-get install python-msgpack" as root.')
|
||||
else:
|
||||
logger.error('If your package manager does not have this package, try running "pip install msgpack-python".')
|
||||
logger.error(
|
||||
'If your package manager does not have'
|
||||
' this package, try running'
|
||||
' "pip install msgpack-python".')
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def check_dependencies(verbose=False, optional=False):
|
||||
"""Do dependency check.
|
||||
|
||||
|
@ -289,17 +366,23 @@ def check_dependencies(verbose = False, optional = False):
|
|||
|
||||
has_all_dependencies = True
|
||||
|
||||
#Python 2.7.3 is the required minimum. Python 3+ is not supported, but it is
|
||||
#still useful to provide information about our other requirements.
|
||||
# Python 2.7.3 is the required minimum. Python 3+ is not supported,
|
||||
# but it is still useful to provide information about our other
|
||||
# requirements.
|
||||
logger.info('Python version: %s', sys.version)
|
||||
if sys.hexversion < 0x20703F0:
|
||||
logger.error('PyBitmessage requires Python 2.7.3 or greater (but not Python 3+)')
|
||||
logger.error(
|
||||
'PyBitmessage requires Python 2.7.3 or greater'
|
||||
' (but not Python 3+)')
|
||||
has_all_dependencies = False
|
||||
if sys.hexversion >= 0x3000000:
|
||||
logger.error('PyBitmessage does not support Python 3+. Python 2.7.3 or greater is required.')
|
||||
logger.error(
|
||||
'PyBitmessage does not support Python 3+. Python 2.7.3'
|
||||
' or greater is required.')
|
||||
has_all_dependencies = False
|
||||
|
||||
check_functions = [check_hashlib, check_sqlite, check_openssl, check_msgpack]
|
||||
check_functions = [
|
||||
check_hashlib, check_sqlite, check_openssl, check_msgpack]
|
||||
if optional:
|
||||
check_functions.extend([check_pyqt, check_curses])
|
||||
|
||||
|
@ -308,14 +391,16 @@ def check_dependencies(verbose = False, optional = False):
|
|||
try:
|
||||
has_all_dependencies &= check()
|
||||
except:
|
||||
logger.exception(check.__name__ + ' failed unexpectedly.')
|
||||
logger.exception('%s failed unexpectedly.', check.__name__)
|
||||
has_all_dependencies = False
|
||||
|
||||
if not has_all_dependencies:
|
||||
logger.critical('PyBitmessage cannot start. One or more dependencies are unavailable.')
|
||||
sys.exit()
|
||||
sys.exit(
|
||||
'PyBitmessage cannot start. One or more dependencies are'
|
||||
' unavailable.'
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
"""Check Dependencies"""
|
||||
check_dependencies(True, True)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user