tobiko/roles/tobiko-ensure-python3/files/get_python_info.py

128 lines
3.8 KiB
Python

# Copyright 2018 Red Hat
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import absolute_import
import argparse
import json
import logging
import os
import subprocess
import sys
LOG = logging.getLogger(__name__)
GET_PYTHON_VERSION_SCRIPT = """
import sys
version = '.'.join(str(i) for i in sys.version_info)
print(version)
"""
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--quiet', '-q',
action="store_true",
help="mute logging messages from STDERR")
parser.add_argument('--base', '-b',
action="store_true",
help="print Python base prefix")
args = parser.parse_args()
setup_logging(quiet=args.quiet)
version = get_python_version()
executables = [
info['executable']
for info in iter_python_executables_info(match_version=version,
base=args.base)]
info = {'version': version,
'executable': sys.executable,
'executables': executables}
output = json.dumps(info, indent=4, sort_keys=True)
print(output)
def setup_logging(quiet=False):
if quiet:
level = logging.ERROR
else:
level = logging.DEBUG
logging.basicConfig(
level=level,
stream=sys.stderr,
format='%(name)-s: %(levelname)-7s %(asctime)-15s | %(message)s')
def get_python_version():
return '.'.join(str(i) for i in sys.version_info)
def iter_python_executables_info(match_version=None, base=None):
last_error = None
for executable in iter_python_executables(base=base):
command = subprocess.list2cmdline(
[executable, '-c', GET_PYTHON_VERSION_SCRIPT])
try:
version = execute(command).splitlines()[0]
except subprocess.CalledProcessError:
LOG.exception('Unable to get version from script')
else:
if not match_version or match_version == version:
yield {'executable': executable, 'version': version}
else:
if last_error:
raise last_error
def iter_python_executables(base):
if base:
prefix = getattr(sys, 'base_prefix', sys.prefix)
else:
prefix = sys.prefix
if prefix:
if os.path.isdir(prefix):
for python_name in iter_versioned_names():
executable = os.path.join(prefix, 'bin', python_name)
if os.path.isfile(executable):
yield executable
def iter_versioned_names(unversioned=None):
unversioned = unversioned or 'python'
short_versioned = unversioned + str(sys.version_info[0])
long_versioned = '.'.join([short_versioned, str(sys.version_info[1])])
yield long_versioned
yield short_versioned
yield unversioned
def execute(command, *args, **kwargs):
if args or kwargs:
command = command.format(*args, **kwargs)
LOG.debug('%s', command)
env = kwargs.get('env', None)
return subprocess.check_output(command, shell=True,
universal_newlines=True,
env=env)
def name_from_path(path):
return os.path.splitext(os.path.basename(path))[0]
if __name__ == '__main__':
LOG = logging.getLogger(name_from_path(__file__))
main()