Skip to content

Instantly share code, notes, and snippets.

@marcusrbrown
Created December 6, 2012 02:00
Show Gist options
  • Select an option

  • Save marcusrbrown/4221264 to your computer and use it in GitHub Desktop.

Select an option

Save marcusrbrown/4221264 to your computer and use it in GitHub Desktop.
Initialize pywin32 in a new virtualenv on Windows
"""Fix a Windows virtualenv by bringing over pywin32 and friends."""
# Based on code found in fablib (https://github.com/srid/fablib/), specifically
# https://github.com/srid/fablib/blob/master/venv.py.
import sys
if sys.platform != 'win32':
print("%s is only available on Windows." % sys.argv[0])
sys.exit(0)
import glob
import os
import shutil
from contextlib import contextmanager
from fabric.api import hide, local, puts
def copy_pywin32_to_virtualenv(python, venv_root):
get_sp = '"import distutils.sysconfig as sc; print(sc.get_python_lib())"'
with hide('everything'):
sp = local(' '.join([python, '-c', get_sp]), capture=True).strip()
pywin32_pth = os.path.join(sp, 'pywin32.pth')
venv_sp = os.path.join(venv_root, 'Lib', 'site-packages')
if not os.path.exists(venv_sp):
os.makedirs(venv_sp)
if os.path.exists(pywin32_pth):
target = os.path.join(venv_sp, 'pywin32.pth')
with msg("Importing global PyWin32 package to '%s'" % venv_sp):
shutil.copyfile(pywin32_pth, target)
# Make all paths in the virtualenv version absolute.
patched_pth = []
for line in open(target, 'r').readlines():
if line.strip() and not line.startswith('#'):
patched_pth.append(os.path.join(sp, line))
else:
patched_pth.append(line)
with open(target, 'w') as f:
f.writelines(patched_pth)
# Copy the remaining PyWin32 packages, win32com, etc.
sources = glob.glob(os.path.join(sp, 'win32*'))
sources.append(os.path.join(sp, 'pythoncom.py'))
for source in sources:
target = os.path.join(venv_sp, os.path.basename(source))
with msg("Copying '%s' to '%s'" % (source, target)):
if os.path.isfile(source):
shutil.copyfile(source, target)
else:
# From fablib: copytree..mkdir will fail if `target` exists;
# workaround that
if os.path.exists(target):
shutil.rmtree(target)
shutil.copytree(source, target)
@contextmanager
def msg(txt):
puts(txt + '...', end='', flush=True)
with hide('everything'):
yield
puts('done.', show_prefix=False, flush=True)
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Usage %s <path to virtualenv>" % sys.argv[0])
sys.exit(1)
venv_root = os.path.abspath(sys.argv[1])
if not os.path.exists(venv_root) or not os.path.isdir(venv_root):
print("Path '%s' is not a directory!" % venv_root)
sys.exit(1)
# Assume that the executable running this script is the system Python.
python = sys.executable
copy_pywin32_to_virtualenv(python, venv_root)
#!/bin/bash
# This hook is run after a new virtualenv is created and before it is activated.
envname=$1
# On Windows, we need to import PyWin32 into the new virtualenv, otherwise packages that depend on it will break.
if [[ "$OS" == "Windows_NT" && -f "$HOME/bin/fix-windows-virtualenv.py" ]]; then
python "$HOME/bin/fix-windows-virtualenv.py" "$WORKON_HOME/$envname"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment