Reused depends in checkdeps script and formatted it also,

made checkdeps executable instead of depends
This commit is contained in:
Dmitri Bogomolov 2018-05-22 14:16:13 +03:00
parent 701521c55a
commit 9f8955ccdd
Signed by untrusted user: g1itch
GPG Key ID: 720A756F18DEED13
2 changed files with 232 additions and 276 deletions

203
checkdeps.py Normal file → Executable file
View File

@ -1,3 +1,4 @@
#!/usr/bin/env python2
"""
Check dependendies and give recommendations about how to satisfy them
@ -9,112 +10,24 @@ Limitations:
EXTRAS_REQUIRE. This is fine because most developers do, too.
"""
import os
from distutils.errors import CompileError
try:
from setuptools.dist import Distribution
from setuptools.extension import Extension
from setuptools.command.build_ext import build_ext
HAVE_SETUPTOOLS = True
# another import from setuptools is in setup.py
from setup import EXTRAS_REQUIRE
except ImportError:
HAVE_SETUPTOOLS = False
EXTRAS_REQUIRE = []
from importlib import import_module
import os
import sys
from setup import EXTRAS_REQUIRE
from src.depends import detectOS, PACKAGES, PACKAGE_MANAGER
PROJECT_ROOT = os.path.abspath('..')
sys.path.insert(0, PROJECT_ROOT)
# OS-specific dependencies for optional components listed in EXTRAS_REQUIRE
EXTRAS_REQUIRE_DEPS = {
# The values from setup.EXTRAS_REQUIRE
'python_prctl': {
# The packages needed for this requirement, by OS
"OpenBSD": [""],
"FreeBSD": [""],
"Debian": ["libcap-dev"],
"Ubuntu": [""],
"Ubuntu 12": [""],
"openSUSE": [""],
"Fedora": [""],
"Guix": [""],
"Gentoo": [""],
},
}
PACKAGE_MANAGER = {
"OpenBSD": "pkg_add",
"FreeBSD": "pkg install",
"Debian": "apt-get install",
"Ubuntu": "apt-get install",
"Ubuntu 12": "apt-get install",
"openSUSE": "zypper install",
"Fedora": "dnf install",
"Guix": "guix package -i",
"Gentoo": "emerge"
}
PACKAGES = {
"PyQt4": {
"OpenBSD": "py-qt4",
"FreeBSD": "py27-qt4",
"Debian": "python-qt4",
"Ubuntu": "python-qt4",
"Ubuntu 12": "python-qt4",
"openSUSE": "python-qt",
"Fedora": "PyQt4",
"Guix": "python2-pyqt@4.11.4",
"Gentoo": "dev-python/PyQt4",
'optional': True,
'description': "You only need PyQt if you want to use the GUI. " \
"When only running as a daemon, this can be skipped.\n" \
"However, you would have to install it manually " \
"because setuptools does not support PyQt."
},
"msgpack": {
"OpenBSD": "py-msgpack",
"FreeBSD": "py27-msgpack-python",
"Debian": "python-msgpack",
"Ubuntu": "python-msgpack",
"Ubuntu 12": "msgpack-python",
"openSUSE": "python-msgpack-python",
"Fedora": "python2-msgpack",
"Guix": "python2-msgpack",
"Gentoo": "dev-python/msgpack",
"optional": True,
"description": "python-msgpack is recommended for improved performance of message encoding/decoding"
},
"pyopencl": {
"FreeBSD": "py27-pyopencl",
"Debian": "python-pyopencl",
"Ubuntu": "python-pyopencl",
"Ubuntu 12": "python-pyopencl",
"Fedora": "python2-pyopencl",
"openSUSE": "",
"OpenBSD": "",
"Guix": "",
"Gentoo": "dev-python/pyopencl",
"optional": True,
'description': "If you install pyopencl, you will be able to use " \
"GPU acceleration for proof of work. \n" \
"You also need a compatible GPU and drivers."
},
"setuptools": {
"OpenBSD": "py-setuptools",
"FreeBSD": "py27-setuptools",
"Debian": "python-setuptools",
"Ubuntu": "python-setuptools",
"Ubuntu 12": "python-setuptools",
"Fedora": "python2-setuptools",
"openSUSE": "python-setuptools",
"Guix": "python2-setuptools",
"Gentoo": "",
"optional": False,
}
}
COMPILING = {
"Debian": "build-essential libssl-dev",
"Ubuntu": "build-essential libssl-dev",
@ -123,46 +36,23 @@ COMPILING = {
"optional": False,
}
def detectOSRelease():
with open("/etc/os-release", 'r') as osRelease:
version = None
for line in osRelease:
if line.startswith("NAME="):
line = line.lower()
if "fedora" in line:
detectOS.result = "Fedora"
elif "opensuse" in line:
detectOS.result = "openSUSE"
elif "ubuntu" in line:
detectOS.result = "Ubuntu"
elif "debian" in line:
detectOS.result = "Debian"
elif "gentoo" in line or "calculate" in line:
detectOS.result = "Gentoo"
else:
detectOS.result = None
if line.startswith("VERSION_ID="):
try:
version = float(line.split("=")[1].replace("\"", ""))
except ValueError:
pass
if detectOS.result == "Ubuntu" and version < 14:
detectOS.result = "Ubuntu 12"
# OS-specific dependencies for optional components listed in EXTRAS_REQUIRE
EXTRAS_REQUIRE_DEPS = {
# The values from setup.EXTRAS_REQUIRE
'python_prctl': {
# The packages needed for this requirement, by OS
"OpenBSD": [""],
"FreeBSD": [""],
"Debian": ["libcap-dev python-prctl"],
"Ubuntu": ["libcap-dev python-prctl"],
"Ubuntu 12": ["libcap-dev python-prctl"],
"openSUSE": [""],
"Fedora": ["prctl"],
"Guix": [""],
"Gentoo": ["dev-python/python-prctl"],
},
}
def detectOS():
if detectOS.result is not None:
return detectOS.result
if sys.platform.startswith('openbsd'):
detectOS.result = "OpenBSD"
elif sys.platform.startswith('freebsd'):
detectOS.result = "FreeBSD"
elif sys.platform.startswith('win'):
detectOS.result = "Windows"
elif os.path.isfile("/etc/os-release"):
detectOSRelease()
elif os.path.isfile("/etc/config.scm"):
detectOS.result = "Guix"
return detectOS.result
def detectPrereqs(missing=True):
available = []
@ -176,18 +66,21 @@ def detectPrereqs(missing=True):
available.append(module)
return available
def prereqToPackages():
if not detectPrereqs():
return
print "%s %s" % (
print("%s %s" % (
PACKAGE_MANAGER[detectOS()], " ".join(
PACKAGES[x][detectOS()] for x in detectPrereqs()))
PACKAGES[x][detectOS()] for x in detectPrereqs())))
def compilerToPackages():
if not detectOS() in COMPILING:
return
print "%s %s" % (
PACKAGE_MANAGER[detectOS.result], COMPILING[detectOS.result])
print("%s %s" % (
PACKAGE_MANAGER[detectOS.result], COMPILING[detectOS.result]))
def testCompiler():
if not HAVE_SETUPTOOLS:
@ -214,30 +107,30 @@ def testCompiler():
fullPath = os.path.join(cmd.build_lib, cmd.get_ext_filename("bitmsghash"))
return os.path.isfile(fullPath)
detectOS.result = None
prereqs = detectPrereqs()
prereqs = detectPrereqs()
compiler = testCompiler()
if (not compiler or prereqs) and detectOS() in PACKAGE_MANAGER:
print "It looks like you're using %s. " \
"It is highly recommended to use the package manager\n" \
"to install the missing dependencies." % (detectOS.result)
print(
"It looks like you're using %s. "
"It is highly recommended to use the package manager\n"
"to install the missing dependencies." % detectOS.result)
if not compiler:
print "Building the bitmsghash module failed.\n" \
"You may be missing a C++ compiler and/or the OpenSSL headers."
print(
"Building the bitmsghash module failed.\n"
"You may be missing a C++ compiler and/or the OpenSSL headers.")
if prereqs:
mandatory = list(x for x in prereqs if "optional" not in PACKAGES[x] or not PACKAGES[x]["optional"])
optional = list(x for x in prereqs if "optional" in PACKAGES[x] and PACKAGES[x]["optional"])
mandatory = [x for x in prereqs if not PACKAGES[x].get("optional")]
optional = [x for x in prereqs if PACKAGES[x].get("optional")]
if mandatory:
print "Missing mandatory dependencies: %s" % (" ".join(mandatory))
print("Missing mandatory dependencies: %s" % " ".join(mandatory))
if optional:
print "Missing optional dependencies: %s" % (" ".join(optional))
print("Missing optional dependencies: %s" % " ".join(optional))
for package in optional:
print PACKAGES[package].get('description')
print(PACKAGES[package].get('description'))
# Install the system dependencies of optional extras_require components
OPSYS = detectOS()
@ -259,12 +152,14 @@ for lhs, rhs in EXTRAS_REQUIRE.items():
if x in EXTRAS_REQUIRE_DEPS
]),
])
print "Optional dependency `pip install .[{}]` would require `{}` to be run as root".format(lhs, rhs_cmd)
print(
"Optional dependency `pip install .[{}]` would require `{}`"
" to be run as root".format(lhs, rhs_cmd))
if (not compiler or prereqs) and detectOS() in PACKAGE_MANAGER:
print "You can install the missing dependencies by running, as root:"
if (not compiler or prereqs) and OPSYS in PACKAGE_MANAGER:
print("You can install the missing dependencies by running, as root:")
if not compiler:
compilerToPackages()
prereqToPackages()
else:
print "All the dependencies satisfied, you can install PyBitmessage"
print("All the dependencies satisfied, you can install PyBitmessage")

View File

@ -1,8 +1,8 @@
#!/usr/bin/env python2
"""
Utility functions to check the availability of dependencies
and suggest how it may be installed
"""
import os
import pyelliptic.openssl
import subprocess
import sys
# Only really old versions of Python don't have sys.hexversion. We don't
@ -14,22 +14,160 @@ if not hasattr(sys, 'hexversion') or sys.hexversion < 0x20300F0:
% sys.version
)
# We can now use logging so set up a simple configuration
import logging
import os
from importlib import import_module
# We can now use logging so set up a simple configuration
formatter = logging.Formatter(
'%(levelname)s: %(message)s'
)
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(formatter)
logger = logging.getLogger(__name__)
logger = logging.getLogger('both')
logger.addHandler(handler)
logger.setLevel(logging.ERROR)
PACKAGE_MANAGER = {
"OpenBSD": "pkg_add",
"FreeBSD": "pkg install",
"Debian": "apt-get install",
"Ubuntu": "apt-get install",
"Ubuntu 12": "apt-get install",
"openSUSE": "zypper install",
"Fedora": "dnf install",
"Guix": "guix package -i",
"Gentoo": "emerge"
}
PACKAGES = {
"PyQt4": {
"OpenBSD": "py-qt4",
"FreeBSD": "py27-qt4",
"Debian": "python-qt4",
"Ubuntu": "python-qt4",
"Ubuntu 12": "python-qt4",
"openSUSE": "python-qt",
"Fedora": "PyQt4",
"Guix": "python2-pyqt@4.11.4",
"Gentoo": "dev-python/PyQt4",
"optional": True,
"description":
"You only need PyQt if you want to use the GUI."
" When only running as a daemon, this can be skipped.\n"
"However, you would have to install it manually"
" because setuptools does not support PyQt."
},
"msgpack": {
"OpenBSD": "py-msgpack",
"FreeBSD": "py27-msgpack-python",
"Debian": "python-msgpack",
"Ubuntu": "python-msgpack",
"Ubuntu 12": "msgpack-python",
"openSUSE": "python-msgpack-python",
"Fedora": "python2-msgpack",
"Guix": "python2-msgpack",
"Gentoo": "dev-python/msgpack",
"optional": True,
"description":
"python-msgpack is recommended for improved performance of"
" message encoding/decoding"
},
"pyopencl": {
"FreeBSD": "py27-pyopencl",
"Debian": "python-pyopencl",
"Ubuntu": "python-pyopencl",
"Ubuntu 12": "python-pyopencl",
"Fedora": "python2-pyopencl",
"openSUSE": "",
"OpenBSD": "",
"Guix": "",
"Gentoo": "dev-python/pyopencl",
"optional": True,
"description":
"If you install pyopencl, you will be able to use"
" GPU acceleration for proof of work.\n"
"You also need a compatible GPU and drivers."
},
"setuptools": {
"OpenBSD": "py-setuptools",
"FreeBSD": "py27-setuptools",
"Debian": "python-setuptools",
"Ubuntu": "python-setuptools",
"Ubuntu 12": "python-setuptools",
"Fedora": "python2-setuptools",
"openSUSE": "python-setuptools",
"Guix": "python2-setuptools",
"Gentoo": "dev-python/setuptools",
"optional": False,
}
}
def detectOS():
if detectOS.result is not None:
return detectOS.result
if sys.platform.startswith('openbsd'):
detectOS.result = "OpenBSD"
elif sys.platform.startswith('freebsd'):
detectOS.result = "FreeBSD"
elif sys.platform.startswith('win'):
detectOS.result = "Windows"
elif os.path.isfile("/etc/os-release"):
detectOSRelease()
elif os.path.isfile("/etc/config.scm"):
detectOS.result = "Guix"
return detectOS.result
detectOS.result = None
def detectOSRelease():
with open("/etc/os-release", 'r') as osRelease:
version = None
for line in osRelease:
if line.startswith("NAME="):
line = line.lower()
if "fedora" in line:
detectOS.result = "Fedora"
elif "opensuse" in line:
detectOS.result = "openSUSE"
elif "ubuntu" in line:
detectOS.result = "Ubuntu"
elif "debian" in line:
detectOS.result = "Debian"
elif "gentoo" in line or "calculate" in line:
detectOS.result = "Gentoo"
else:
detectOS.result = None
if line.startswith("VERSION_ID="):
try:
version = float(line.split("=")[1].replace("\"", ""))
except ValueError:
pass
if detectOS.result == "Ubuntu" and version < 14:
detectOS.result = "Ubuntu 12"
def try_import(module, log_extra=False):
try:
return import_module(module)
except ImportError:
module = module.split('.')[0]
logger.error('The %s module is not available.', module)
if log_extra:
logger.error(log_extra)
dist = detectOS()
logger.error(
'On %s, try running "%s %s" as root.',
dist, PACKAGE_MANAGER[dist], PACKAGES[module][dist])
return False
# We need to check hashlib for RIPEMD-160, as it won't be available
# if OpenSSL is not linked against or the linked OpenSSL has RIPEMD
# disabled.
def check_hashlib():
"""Do hashlib check.
@ -73,19 +211,18 @@ def check_sqlite():
logger.error(
'On FreeBSD, try running "pkg install py27-sqlite3" as root.')
return False
try:
import sqlite3
except ImportError:
logger.error('The sqlite3 module is not available')
sqlite3 = try_import('sqlite3')
if not sqlite3:
return False
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]
sqlite3.sqlite_version_info[0] * 1000000 +
sqlite3.sqlite_version_info[1] * 1000 +
sqlite3.sqlite_version_info[2]
)
conn = None
@ -126,11 +263,10 @@ def check_openssl():
Here we are checking for openssl with its all dependent libraries
and version checking.
"""
try:
import ctypes
except ImportError:
logger.error(
'Unable to check OpenSSL. The ctypes module is not available.')
ctypes = try_import('ctypes')
if not ctypes:
logger.error('Unable to check OpenSSL.')
return False
# We need to emulate the way PyElliptic searches for OpenSSL.
@ -163,6 +299,8 @@ def check_openssl():
cflags_regex = re.compile(r'(?:OPENSSL_NO_)(AES|EC|ECDH|ECDSA)(?!\w)')
import pyelliptic.openssl
for path in paths:
logger.info('Checking OpenSSL at %s', path)
try:
@ -213,21 +351,20 @@ def check_curses():
'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.')
curses = try_import('curses')
if not curses:
logger.error('The curses interface can not be used.')
return False
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.')
dialog = try_import('dialog')
if not dialog:
logger.error('The curses interface can not be used.')
return False
import subprocess
try:
subprocess.check_call('which dialog')
except subprocess.CalledProcessError:
@ -249,54 +386,23 @@ def check_pyqt():
"""Do pyqt dependency check.
Here we are checking for PyQt4 with its version, as for it require
PyQt 4.7 or later.
PyQt 4.8 or later.
"""
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.')
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.')
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.')
elif "opensuse" in line.lower():
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.')
elif "debian" in line.lower():
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".')
QtCore = try_import(
'PyQt4.QtCore', 'PyBitmessage requires PyQt 4.8 or later and Qt 4.7 or later.')
if not QtCore:
return False
logger.info('PyQt Version: %s', PyQt4.QtCore.PYQT_VERSION_STR)
logger.info('Qt Version: %s', PyQt4.QtCore.QT_VERSION_STR)
logger.info('PyQt Version: %s', QtCore.PYQT_VERSION_STR)
logger.info('Qt Version: %s', QtCore.QT_VERSION_STR)
passed = True
if PyQt4.QtCore.PYQT_VERSION < 0x40800:
if QtCore.PYQT_VERSION < 0x40800:
logger.error(
'This version of PyQt is too old. PyBitmessage requries'
' PyQt 4.8 or later.')
passed = False
if PyQt4.QtCore.QT_VERSION < 0x40700:
if QtCore.QT_VERSION < 0x40700:
logger.error(
'This version of Qt is too old. PyBitmessage requries'
' Qt 4.7 or later.')
@ -310,47 +416,8 @@ def check_msgpack():
simply checking if msgpack package with all its dependency
is available or not as recommended for messages coding.
"""
try:
import msgpack
except ImportError:
logger.error(
'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.')
elif sys.platform.startswith('freebsd'):
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.')
elif "opensuse" in line.lower():
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.')
elif "debian" in line.lower():
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".')
return True
return try_import(
'msgpack', 'It is highly recommended for messages coding.') is not False
def check_dependencies(verbose=False, optional=False):
@ -381,10 +448,9 @@ def check_dependencies(verbose=False, optional=False):
' 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]
if optional:
check_functions.extend([check_pyqt, check_curses])
check_functions.extend([check_msgpack, check_pyqt, check_curses])
# Unexpected exceptions are handled here
for check in check_functions:
@ -399,8 +465,3 @@ def check_dependencies(verbose=False, optional=False):
'PyBitmessage cannot start. One or more dependencies are'
' unavailable.'
)
if __name__ == '__main__':
"""Check Dependencies"""
check_dependencies(True, True)