test_ok1/py/misc/_dist.py

209 lines
6.4 KiB
Python

import py
import sys, os, re
from distutils import sysconfig
from distutils import core
try:
import subprocess
except ImportError:
from py.__.compat import subprocess
winextensions = 1
if sys.platform == 'win32':
try:
import _winreg, win32gui, win32con
except ImportError:
winextensions = 0
class Params:
""" a crazy hack to convince distutils to please
install all of our files inside the package.
"""
_sitepackages = py.path.local(sysconfig.get_python_lib())
def __init__(self, pkgmod):
name = pkgmod.__name__
self._pkgdir = py.path.local(pkgmod.__file__).dirpath()
self._rootdir = self._pkgdir.dirpath()
self._pkgtarget = self._sitepackages.join(name)
self._datadict = {}
self.packages = []
self.scripts = []
self.hacktree()
self.data_files = self._datadict.items()
self.data_files.sort()
self.packages.sort()
self.scripts.sort()
def hacktree(self):
for p in self._pkgdir.visit(None, lambda x: x.basename != '.svn'):
if p.check(file=1):
if p.ext in ('.pyc', '.pyo'):
continue
if p.dirpath().basename == 'bin':
self.scripts.append(p.relto(self._rootdir))
self.adddatafile(p)
elif p.ext == '.py':
self.addpythonfile(p)
else:
self.adddatafile(p)
#else:
# if not p.listdir():
# self.adddatafile(p.ensure('dummy'))
def adddatafile(self, p):
if p.ext in ('.pyc', 'pyo'):
return
target = self._pkgtarget.join(p.dirpath().relto(self._pkgdir))
l = self._datadict.setdefault(str(target), [])
l.append(p.relto(self._rootdir))
def addpythonfile(self, p):
parts = p.parts()
for above in p.parts(reverse=True)[1:]:
if self._pkgdir.relto(above):
dottedname = p.dirpath().relto(self._rootdir).replace(p.sep, '.')
if dottedname not in self.packages:
self.packages.append(dottedname)
break
if not above.join('__init__.py').check():
self.adddatafile(p)
#print "warning, added data file", p
break
#if sys.platform != 'win32':
# scripts.remove('py/bin/pytest.cmd')
#else:
# scripts.remove('py/bin/py.test')
#
### helpers:
def checknonsvndir(p):
if p.basename != '.svn' and p.check(dir=1):
return True
def dump(params):
print "packages"
for x in params.packages:
print "package ", x
print
print "scripts"
for x in params.scripts:
print "script ", x
print
print "data files"
for x in params.data_files:
print "data file ", x
print
def addbindir2path():
if sys.platform != 'win32' or not winextensions:
return
# Add py/bin to PATH environment variable
bindir = os.path.join(sysconfig.get_python_lib(), "py", "bin", "win32")
# check for the user path
ureg = _winreg.ConnectRegistry(None, _winreg.HKEY_CURRENT_USER)
ukey = r"Environment"
# not every user has his own path on windows
try:
upath = get_registry_value(ureg, ukey, "PATH")
except WindowsError:
upath=""
# if bindir allready in userpath -> do nothing
if bindir in upath:
return
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
key = r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
path = get_registry_value(reg, key, "Path")
# if bindir allready in systempath -> do nothing
if bindir in path:
return
path += ";" + bindir
print "Setting PATH to:", path
pathset=False
try:
set_registry_value(reg, key, "PATH", path)
pathset=True
except WindowsError:
print "cannot set systempath, falling back to userpath"
pass
if not pathset:
try:
if len(upath)>0: #if no user path present
upath += ";"
upath+=bindir
set_registry_value(ureg, ukey, "Path", upath)
pathset=True
except WindowsError:
print "cannot set userpath, please add %s to your path" % (bindir,)
return
#print "Current PATH is:", get_registry_value(reg, key, "Path")
# Propagate changes throughout the system
win32gui.SendMessageTimeout(win32con.HWND_BROADCAST,
win32con.WM_SETTINGCHANGE, 0, "Environment",
win32con.SMTO_ABORTIFHUNG, 5000)
# Propagate changes to current command prompt
p = subprocess.Popen("set PATH=%s" % path, shell=True)
os.waitpid(p.pid, 0)
def get_registry_value(reg, key, value_name):
k = _winreg.OpenKey(reg, key)
value = _winreg.QueryValueEx(k, value_name)[0]
_winreg.CloseKey(k)
return value
def set_registry_value(reg, key, value_name, value):
k = _winreg.OpenKey(reg, key, 0, _winreg.KEY_WRITE)
value_type = _winreg.REG_SZ
# if we handle the Path value, then set its type to REG_EXPAND_SZ
# so that things like %SystemRoot% get automatically expanded by the
# command prompt
if value_name == "Path":
value_type = _winreg.REG_EXPAND_SZ
_winreg.SetValueEx(k, value_name, 0, value_type, value)
_winreg.CloseKey(k)
### end helpers
def setup(pkg, **kw):
""" invoke distutils on a given package.
"""
if 'install' in sys.argv[1:]:
print "precompiling greenlet module"
try:
x = py.magic.greenlet()
except (RuntimeError, ImportError):
print "could not precompile greenlet module, skipping"
params = Params(pkg)
#dump(params)
source = getattr(pkg, '__pkg__', pkg)
namelist = list(core.setup_keywords)
namelist.extend(['packages', 'scripts', 'data_files'])
for name in namelist:
for ns in (source, params):
if hasattr(ns, name):
kw[name] = getattr(ns, name)
break
#script_args = sys.argv[1:]
#if 'install' in script_args:
# script_args = ['--quiet'] + script_args
# #print "installing", py
#py.std.pprint.pprint(kw)
core.setup(**kw)
if 'install' in sys.argv[1:]:
addbindir2path()
x = params._rootdir.join('build')
if x.check():
print "removing", x
x.remove()