raise PackagingError, ("could not parse %s due to %s: %s"
% (what or repr(verstr), cls.__name__, value)), trace
+def get_openssl_version():
+ try:
+ from OpenSSL import SSL
+ return extract_openssl_version(SSL)
+ except Exception:
+ return ("unknown", None, None)
+
+def extract_openssl_version(ssl_module):
+ openssl_version = ssl_module.SSLeay_version(ssl_module.SSLEAY_VERSION)
+ if openssl_version.startswith('OpenSSL '):
+ openssl_version = openssl_version[8 :]
+
+ (version, _, comment) = openssl_version.partition(' ')
+
+ try:
+ openssl_cflags = ssl_module.SSLeay_version(ssl_module.SSLEAY_CFLAGS)
+ if '-DOPENSSL_NO_HEARTBEATS' in openssl_cflags.split(' '):
+ comment += ", no heartbeats"
+ except Exception:
+ pass
+
+ return (version, None, comment if comment else None)
def get_package_versions_and_locations():
import warnings
packages = []
- def get_version(module, attr):
- return str(getattr(module, attr, 'unknown'))
+ def get_version(module):
+ if hasattr(module, '__version__'):
+ return str(getattr(module, '__version__'))
+ elif hasattr(module, 'version'):
+ ver = getattr(module, 'version')
+ if isinstance(ver, tuple):
+ return '.'.join(map(str, ver))
+ else:
+ return str(ver)
+ else:
+ return 'unknown'
for pkgname, modulename in [(__appname__, 'allmydata')] + package_imports:
if modulename:
elif pkgname == 'setuptools' and hasattr(module, '_distribute'):
# distribute does not report its version in any module variables
comment = 'distribute'
- packages.append( (pkgname, (get_version(module, '__version__'), package_dir(module.__file__), comment)) )
+ packages.append( (pkgname, (get_version(module), package_dir(module.__file__), comment)) )
elif pkgname == 'python':
packages.append( (pkgname, (platform.python_version(), sys.executable, None)) )
elif pkgname == 'platform':
packages.append( (pkgname, (get_platform(), None, None)) )
+ elif pkgname == 'OpenSSL':
+ packages.append( (pkgname, get_openssl_version()) )
return packages
def check_requirement(req, vers_and_locs):
- # TODO: check [] options
- # We support only disjunctions of <=, >=, and ==
+ # We support only conjunctions of <=, >=, and !=
reqlist = req.split(',')
- name = reqlist[0].split('<=')[0].split('>=')[0].split('==')[0].strip(' ').split('[')[0]
+ name = reqlist[0].split('<=')[0].split('>=')[0].split('!=')[0].strip(' ').split('[')[0]
if name not in vers_and_locs:
raise PackagingError("no version info for %s" % (name,))
if req.strip(' ') == name:
return
actualver = normalized_version(actual, what="actual version %r of %s from %r" % (actual, name, location))
+ if not match_requirement(req, reqlist, actualver):
+ msg = ("We require %s, but could only find version %s.\n" % (req, actual))
+ if location and location != 'unknown':
+ msg += "The version we found is from %r.\n" % (location,)
+ msg += ("To resolve this problem, uninstall that version, either using your\n"
+ "operating system's package manager or by moving aside the directory.")
+ raise PackagingError(msg)
+
+
+def match_requirement(req, reqlist, actualver):
for r in reqlist:
s = r.split('<=')
if len(s) == 2:
required = s[1].strip(' ')
- if actualver <= normalized_version(required, what="required maximum version %r in %r" % (required, req)):
- return # maximum requirement met
+ if not (actualver <= normalized_version(required, what="required maximum version %r in %r" % (required, req))):
+ return False # maximum requirement not met
else:
s = r.split('>=')
if len(s) == 2:
required = s[1].strip(' ')
- if actualver >= normalized_version(required, what="required minimum version %r in %r" % (required, req)):
- return # minimum requirement met
+ if not (actualver >= normalized_version(required, what="required minimum version %r in %r" % (required, req))):
+ return False # minimum requirement not met
else:
- s = r.split('==')
+ s = r.split('!=')
if len(s) == 2:
required = s[1].strip(' ')
- if actualver == normalized_version(required, what="required exact version %r in %r" % (required, req)):
- return # exact requirement met
+ if not (actualver != normalized_version(required, what="excluded version %r in %r" % (required, req))):
+ return False # not-equal requirement not met
else:
raise PackagingError("no version info or could not understand requirement %r" % (req,))
- msg = ("We require %s, but could only find version %s.\n" % (req, actual))
- if location and location != 'unknown':
- msg += "The version we found is from %r.\n" % (location,)
- msg += ("To resolve this problem, uninstall that version, either using your\n"
- "operating system's package manager or by moving aside the directory.")
- raise PackagingError(msg)
+ return True
_vers_and_locs_list = get_package_versions_and_locations()
from _auto_deps import not_import_versionable, ignorable
errors = []
- not_pkg_resourceable = ['python', 'platform', __appname__.lower()]
+ not_pkg_resourceable = ['python', 'platform', __appname__.lower(), 'openssl']
for name, (imp_ver, imp_loc, imp_comment) in imported_vers_and_locs_list:
name = name.lower()