flake8: depends

This commit is contained in:
Dmitri Bogomolov 2018-04-18 13:34:12 +03:00
parent b27cc071a2
commit 701521c55a
Signed by untrusted user: g1itch
GPG Key ID: 720A756F18DEED13

View File

@ -1,16 +1,18 @@
#! python #!/usr/bin/env python2
import subprocess
import sys
import os import os
import pyelliptic.openssl import pyelliptic.openssl
import subprocess
import sys
# Only really old versions of Python don't have sys.hexversion. We don't # 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 # support them. The logging module was introduced in Python 2.3
if not hasattr(sys, 'hexversion') or sys.hexversion < 0x20300F0: if not hasattr(sys, 'hexversion') or sys.hexversion < 0x20300F0:
sys.stdout.write('Python version: ' + sys.version) sys.exit(
sys.stdout.write('PyBitmessage requires Python 2.7.3 or greater (but not Python 3)') 'Python version: %s\n'
sys.exit() '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 # We can now use logging so set up a simple configuration
import logging import logging
@ -32,22 +34,28 @@ def check_hashlib():
"""Do hashlib check. """Do hashlib check.
The hashlib module check with version as if it included or not 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 interface to the most popular hashing algorithms. hashlib
implements some of the algorithms, however if OpenSSL implements some of the algorithms, however if OpenSSL
installed, hashlib is able to use this algorithms as well. installed, hashlib is able to use this algorithms as well.
""" """
if sys.hexversion < 0x020500F0: 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 return False
import hashlib import hashlib
if '_hashlib' not in hashlib.__dict__: 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 return False
try: try:
hashlib.new('ripemd160') hashlib.new('ripemd160')
except ValueError: 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 False
return True return True
@ -59,9 +67,11 @@ def check_sqlite():
support in python version for specifieed platform. support in python version for specifieed platform.
""" """
if sys.hexversion < 0x020500F0: 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'): 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 return False
try: try:
import sqlite3 import sqlite3
@ -69,25 +79,37 @@ def check_sqlite():
logger.error('The sqlite3 module is not available') logger.error('The sqlite3 module is not available')
return False return False
logger.info('sqlite3 Module Version: ' + sqlite3.version) logger.info('sqlite3 Module Version: %s', sqlite3.version)
logger.info('SQLite Library Version: ' + sqlite3.sqlite_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 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 conn = None
try: try:
try: try:
conn = sqlite3.connect(':memory:') conn = sqlite3.connect(':memory:')
if sqlite_version_number >= 3006018: if sqlite_version_number >= 3006018:
sqlite_source_id = conn.execute('SELECT sqlite_source_id();').fetchone()[0] sqlite_source_id = conn.execute(
logger.info('SQLite Library Source ID: ' + sqlite_source_id) 'SELECT sqlite_source_id();'
).fetchone()[0]
logger.info('SQLite Library Source ID: %s', sqlite_source_id)
if sqlite_version_number >= 3006023: if sqlite_version_number >= 3006023:
compile_options = ', '.join(map(lambda row: row[0], conn.execute('PRAGMA compile_options;'))) compile_options = ', '.join(map(
logger.info('SQLite Library Compile Options: ' + compile_options) lambda row: row[0],
#There is no specific version requirement as yet, so we just use the conn.execute('PRAGMA compile_options;')
#first version that was included with Python. ))
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: 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 False
return True return True
except sqlite3.Error: except sqlite3.Error:
@ -97,6 +119,7 @@ def check_sqlite():
if conn: if conn:
conn.close() conn.close()
def check_openssl(): def check_openssl():
"""Do openssl dependency check. """Do openssl dependency check.
@ -106,7 +129,8 @@ def check_openssl():
try: try:
import ctypes import ctypes
except ImportError: 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 return False
# We need to emulate the way PyElliptic searches for OpenSSL. # 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)') cflags_regex = re.compile(r'(?:OPENSSL_NO_)(AES|EC|ECDH|ECDSA)(?!\w)')
for path in paths: for path in paths:
logger.info('Checking OpenSSL at ' + path) logger.info('Checking OpenSSL at %s', path)
try: try:
library = ctypes.CDLL(path) library = ctypes.CDLL(path)
except OSError: except OSError:
continue continue
logger.info('OpenSSL Name: ' + library._name) logger.info('OpenSSL Name: %s', library._name)
try: 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 except AttributeError: # sphinx chokes
return True return True
if not openssl_version: if not openssl_version:
logger.error('Cannot determine version of this OpenSSL library.') logger.error('Cannot determine version of this OpenSSL library.')
return False return False
logger.info('OpenSSL Version: ' + openssl_version) logger.info('OpenSSL Version: %s', openssl_version)
logger.info('OpenSSL Compile Options: ' + openssl_cflags) logger.info('OpenSSL Compile Options: %s', openssl_cflags)
# PyElliptic uses EVP_CIPHER_CTX_new and EVP_CIPHER_CTX_free which were # PyElliptic uses EVP_CIPHER_CTX_new and EVP_CIPHER_CTX_free which were
# introduced in 0.9.8b. # introduced in 0.9.8b.
if openssl_hexversion < 0x90802F: 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 return False
matches = cflags_regex.findall(openssl_cflags) matches = cflags_regex.findall(openssl_cflags)
if len(matches) > 0: 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 False
return True return True
return False return False
# TODO: The minimum versions of pythondialog and dialog need to be determined # TODO: The minimum versions of pythondialog and dialog need to be determined
def check_curses(): def check_curses():
"""Do curses dependency check. """Do curses dependency check.
@ -176,33 +209,42 @@ def check_curses():
utility. utility.
""" """
if sys.hexversion < 0x20600F0: 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 return False
try: try:
import curses import curses
except ImportError: 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 return False
logger.info('curses Module Version: ' + curses.version) logger.info('curses Module Version: %s', curses.version)
try: try:
import dialog import dialog
except ImportError: 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 return False
try: try:
subprocess.check_call('which dialog') subprocess.check_call('which dialog')
except subprocess.CalledProcessError: 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 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 dialog_util_version = dialog.Dialog().cached_backend_version
# The pythondialog author does not like Python2 str, so we have to use # 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 # unicode for just the version otherwise we get the repr form which
#the module and class names along with the actual version. # includes the module and class names along with the actual version.
logger.info('dialog Utility Version' + unicode(dialog_util_version)) logger.info('dialog Utility Version %s', unicode(dialog_util_version))
return True return True
def check_pyqt(): def check_pyqt():
"""Do pyqt dependency check. """Do pyqt dependency check.
@ -212,37 +254,56 @@ def check_pyqt():
try: try:
import PyQt4.QtCore import PyQt4.QtCore
except ImportError: 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'): if sys.platform.startswith('openbsd'):
logger.error('On OpenBSD, try running "pkg_add py-qt4" as root.') logger.error('On OpenBSD, try running "pkg_add py-qt4" as root.')
elif sys.platform.startswith('freebsd'): 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"): elif os.path.isfile("/etc/os-release"):
with open("/etc/os-release", 'rt') as osRelease: with open("/etc/os-release", 'rt') as osRelease:
for line in osRelease: for line in osRelease:
if line.startswith("NAME="): if line.startswith("NAME="):
if "fedora" in line.lower(): 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(): 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(): 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(): 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: 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 return False
logger.info('PyQt Version: ' + PyQt4.QtCore.PYQT_VERSION_STR) logger.info('PyQt Version: %s', PyQt4.QtCore.PYQT_VERSION_STR)
logger.info('Qt Version: ' + PyQt4.QtCore.QT_VERSION_STR) logger.info('Qt Version: %s', PyQt4.QtCore.QT_VERSION_STR)
passed = True passed = True
if PyQt4.QtCore.PYQT_VERSION < 0x40800: 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 passed = False
if PyQt4.QtCore.QT_VERSION < 0x40700: 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 passed = False
return passed return passed
def check_msgpack(): def check_msgpack():
"""Do sgpack module check. """Do sgpack module check.
@ -256,26 +317,42 @@ def check_msgpack():
'The msgpack package is not available.' 'The msgpack package is not available.'
'It is highly recommended for messages coding.') 'It is highly recommended for messages coding.')
if sys.platform.startswith('openbsd'): 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'): 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"): elif os.path.isfile("/etc/os-release"):
with open("/etc/os-release", 'rt') as osRelease: with open("/etc/os-release", 'rt') as osRelease:
for line in osRelease: for line in osRelease:
if line.startswith("NAME="): if line.startswith("NAME="):
if "fedora" in line.lower(): 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(): 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(): 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(): 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: 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 return True
def check_dependencies(verbose=False, optional=False): def check_dependencies(verbose=False, optional=False):
"""Do dependency check. """Do dependency check.
@ -289,17 +366,23 @@ def check_dependencies(verbose = False, optional = False):
has_all_dependencies = True has_all_dependencies = True
#Python 2.7.3 is the required minimum. Python 3+ is not supported, but it is # Python 2.7.3 is the required minimum. Python 3+ is not supported,
#still useful to provide information about our other requirements. # but it is still useful to provide information about our other
# requirements.
logger.info('Python version: %s', sys.version) logger.info('Python version: %s', sys.version)
if sys.hexversion < 0x20703F0: 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 has_all_dependencies = False
if sys.hexversion >= 0x3000000: 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 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: if optional:
check_functions.extend([check_pyqt, check_curses]) check_functions.extend([check_pyqt, check_curses])
@ -308,14 +391,16 @@ def check_dependencies(verbose = False, optional = False):
try: try:
has_all_dependencies &= check() has_all_dependencies &= check()
except: except:
logger.exception(check.__name__ + ' failed unexpectedly.') logger.exception('%s failed unexpectedly.', check.__name__)
has_all_dependencies = False has_all_dependencies = False
if not has_all_dependencies: 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__': if __name__ == '__main__':
"""Check Dependencies""" """Check Dependencies"""
check_dependencies(True, True) check_dependencies(True, True)