|
#!/usr/bin/env python3 |
|
|
|
# For each directory in ~/.virtualenvs check for bad links |
|
# When found, determine python executable linked, delete bad symlinks, reinvoke virtualenv with python flavor. |
|
|
|
import os |
|
import sys |
|
try: |
|
from subprocess import run |
|
except ImportError: |
|
print("Unable to load subprocess.run. Requires at least Python 3.5+") |
|
sys.exit(1) |
|
|
|
|
|
VENV_PATH = os.path.join(os.environ['HOME'], '.virtualenvs') |
|
VIRTUALENV_EXEC = '/usr/local/bin/virtualenv' |
|
GFIND_EXEC = 'gfind' |
|
|
|
def get_venvs(): |
|
return [os.path.join(VENV_PATH, o) for o in os.listdir(VENV_PATH) if os.path.isdir(os.path.join(VENV_PATH,o))] |
|
|
|
def badlink(fpath): |
|
def islink(link_path): |
|
return os.path.islink(link_path) |
|
|
|
def islinkvalid(link_path): |
|
resolved_path = os.readlink(link_path) |
|
return os.path.exists(resolved_path) |
|
|
|
return islink(fpath) and not islinkvalid(fpath) |
|
|
|
def has_badlinks(venv_path): |
|
for dirpath, _, file_list in os.walk(venv_path): |
|
for fname in file_list: |
|
fpath = os.path.join(dirpath, fname) |
|
if badlink(fpath): |
|
return True |
|
return False |
|
|
|
def print_badlinks(venv_path): |
|
for dirpath, _, file_list in os.walk(venv_path): |
|
for fname in file_list: |
|
fpath = os.path.join(dirpath, fname) |
|
if badlink(fpath): |
|
print(fpath) |
|
|
|
|
|
def get_python_exec(path): |
|
full_path = os.path.join(path, 'bin/python') |
|
#print(full_path, os.path.islink(full_path)) |
|
#print(os.path.join(path, '.python'), os.path.islink(os.path.join(path, '.python'))) |
|
if os.path.islink(full_path): |
|
return os.readlink(full_path) |
|
elif os.path.isfile(full_path): |
|
return 'python' |
|
else: |
|
return 'unknown' |
|
|
|
|
|
for venv in get_venvs(): |
|
needs_update = has_badlinks(venv) |
|
pyexec = get_python_exec(venv) |
|
|
|
print('CHECKING {}...'.format(venv)) |
|
if not pyexec: |
|
print('SKIPPING {} because python version not found'.format(venv)) |
|
continue |
|
|
|
if pyexec == 'unknown': |
|
print('SKIPPING {} because python version is unknown'.format(venv)) |
|
continue |
|
|
|
if needs_update: |
|
print('UPDATING {} with exec {}...'.format(venv, pyexec)) |
|
|
|
if pyexec.endswith('pypy'): |
|
print("skipping pypy") |
|
continue |
|
|
|
if pyexec == 'python3.6': |
|
print ('Using python3 rather than python3.6 for {}'.format(venv)) |
|
pyexec = 'python3' |
|
|
|
# Remove dead links |
|
run([GFIND_EXEC, venv, '-type', 'l', '-xtype', 'l', '-delete'], check=True) |
|
# Recreate venv |
|
run([VIRTUALENV_EXEC, '-p', pyexec, venv], check=True) |
|
print('SUCCESS {}'.format(venv)) |
|
else: |
|
print('OK {}'.format(venv)) |