143 lines
4.2 KiB
Python
143 lines
4.2 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[:3])
|
||
|
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, '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[:3])
|
||
|
|
||
|
|
||
|
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=None):
|
||
|
iterated = set()
|
||
|
for executable in _iter_python_executables(base=base):
|
||
|
# Iterate every executable only once
|
||
|
if executable not in iterated:
|
||
|
iterated.add(executable)
|
||
|
yield executable
|
||
|
|
||
|
|
||
|
def _iter_python_executables(base):
|
||
|
if base:
|
||
|
base_prefix = getattr(sys, 'base_prefix', None)
|
||
|
if base_prefix:
|
||
|
for executable in iter_prefix_executables(base_prefix):
|
||
|
yield executable
|
||
|
|
||
|
for executable in iter_prefix_executables(sys.prefix):
|
||
|
yield executable
|
||
|
|
||
|
yield sys.executable
|
||
|
|
||
|
|
||
|
def iter_prefix_executables(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()
|