/
opt
/
cloudlinux
/
venv
/
lib
/
python3.11
/
site-packages
/
clselect
/
clselectpython
/
Upload Filee
HOME
# coding: utf-8 from __future__ import print_function from __future__ import division from __future__ import absolute_import import glob import os import re import errno from subprocess import check_output, CalledProcessError, STDOUT # Used both for config and some state like available_versions cache # mainly because it's easier to put it in cagefs as a one dir # We have symlink to that dir in /etc # for ease of use the selector config and avoiding problem with cagefs CONFIG_DIR = '/usr/share/l.v.e-manager/cl.python' ALT_NAMES = 'alt-python' # It's also used to construct base_dir: ALT_PYTHON_PREFIX = '/opt/alt/python' class PythonError(Exception): """Top level error class for admin's part of Python selector""" pass class PythonConfigError(PythonError): """Generic error class for PythonConfig""" pass def create_config_dirs(): try: os.makedirs(CONFIG_DIR) except OSError as e: if e.errno != errno.EEXIST: # ignore only "File exists" error raise def is_major_version(ver): """Return True if specified MAJOR version is valid for processing""" if not isinstance(ver, str): return False if not re.match(r'^\d+\.\d+$', ver): return False return True def scan_python_versions(): """ Search CL python interpreters and return dict with info about them """ res = {} for folder in glob.glob('{}*'.format(ALT_PYTHON_PREFIX)): # extract major version of python interpreter # get two last digits from the string such as `/opt/alt/python27` maj_ver = ''.join(filter(str.isdigit, folder.split('/')[-1])) maj_ver = f'{maj_ver[0]}.{maj_ver[1:]}' # extract full version of python interpreter # from the string such as `Python 2.7.14` python_bin = '{}/bin/python{}'.format(folder, maj_ver) if not os.path.isfile(python_bin): continue try: # Starting from 3.4, python command output --version information to stdout instead of stderr # https://docs.python.org/3/whatsnew/3.4.html#changes-in-python-command-behavior full_ver = check_output([python_bin, '-V'], text=True, stderr=STDOUT) except CalledProcessError: continue if full_ver != "": full_ver = full_ver.split()[1] res[maj_ver] = { 'full_version': full_ver, 'root_path': folder, } return res __all__ = ( 'CONFIG_DIR', 'ALT_NAMES', 'ALT_PYTHON_PREFIX', 'PythonError', 'PythonConfigError', 'create_config_dirs', 'is_major_version', 'scan_python_versions', )