update listener. add support for twitter regulation messages. update virtualenv
import sys
import os
import os.path
import shutil
import tarfile
import zipfile
import urllib
import platform
import patch
import struct
import glob
import re
join = os.path.join
system_str = platform.system()
URLS = {
#'': {'setup': '', 'url':'', 'local':''},
'DISTRIBUTE': {'setup': 'distribute', 'url':'http://pypi.python.org/packages/source/d/distribute/distribute-0.6.34.tar.gz', 'local':"distribute-0.6.34.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'ANYJSON': {'setup': 'anyjson', 'url':'http://pypi.python.org/packages/source/a/anyjson/anyjson-0.3.3.tar.gz', 'local':"anyjson-0.3.3.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'OAUTH2': { 'setup': 'python-oauth2', 'url':"https://github.com/simplegeo/python-oauth2/tarball/hudson-python-oauth2-211", 'local':"python-oauth2-1.5-211.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'HTTPLIB2': { 'setup': 'httplib2', 'url':'http://pypi.python.org/packages/source/h/httplib2/httplib2-0.8.tar.gz', 'local':"httplib2-0.8.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'LOCKFILE': {'setup': 'lockfile', 'url':'http://code.google.com/p/pylockfile/downloads/detail?name=lockfile-0.9.1.tar.gz', 'local':"lockfile-0.9.1.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'DAEMON': {'setup': 'python-daemon', 'url':'http://pypi.python.org/packages/source/p/python-daemon/python-daemon-1.5.5.tar.gz', 'local':"python-daemon-1.5.5.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'DATEUTIL': {'setup': 'python-dateutil', 'url':'http://pypi.python.org/packages/source/p/python-dateutil/python-dateutil-2.1.tar.gz', 'local':"python-dateutil-2.1.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'PYTZ': {'setup': 'pytz', 'url':'http://pypi.python.org/packages/source/p/pytz/pytz-2013b.tar.bz2', 'local':"pytz-2013b.tar.bz2", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'SIMPLEJSON': {'setup': 'simplejson', 'url':'http://pypi.python.org/packages/source/s/simplejson/simplejson-3.1.3.tar.gz', 'local':"simplejson-3.1.3.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'SQLALCHEMY': {'setup': 'sqlalchemy', 'url':'http://www.python.org/pypi/SQLAlchemy/0.8.1', 'local':"SQLAlchemy-0.8.1.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'TWITTER': {'setup': 'twitter', 'url':'http://pypi.python.org/packages/source/t/twitter/twitter-1.9.2.tar.gz', 'local':"twitter-1.9.2.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'TWITTER-TEXT': {'setup': 'twitter-text', 'url':'https://github.com/dryan/twitter-text-py/archive/master.tar.gz', 'local':"twitter-text-1.0.4.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'REQUESTS': {'setup': 'requests', 'url':'https://github.com/kennethreitz/requests/archive/v1.2.0.tar.gz', 'local':'requests-v1.2.0.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
'OAUTHLIB': {'setup': 'oauthlib', 'url':'https://github.com/idan/oauthlib/archive/0.4.0.tar.gz', 'local':'oauthlib-0.4.0.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
'REQUESTS-OAUTHLIB': {'setup': 'requests-oauthlib', 'url':'https://github.com/requests/requests-oauthlib/archive/master.tar.gz', 'local':'requests-oauthlib-0.3.0.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
'BLESSINGS': {'setup': 'blessings', 'url':'https://github.com/erikrose/blessings/archive/1.5.tar.gz', 'local':'blessings-1.5.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}
}
if system_str == 'Windows':
URLS.update({
'PSYCOPG2': {'setup': 'psycopg2','url': 'psycopg2-2.5.win32-py2.7-pg9.2.4-release.zip', 'local':"psycopg2-2.5.win32-py2.7-pg9.2.4-release.zip", 'install': {'method': 'install_psycopg2', 'option_str': None, 'dict_extra_env': None}},
'LXML': {'setup': 'lxml', 'url': 'http://pypi.python.org/packages/2.7/l/lxml/lxml-2.3-py2.7-win32.egg', 'local':"lxml-2.3-py2.7-win32.egg", 'install': {'method': 'easy_install', 'option_str': None, 'dict_extra_env': None}},
})
else:
if system_str == "Darwin":
lxml_options = {'STATIC_DEPS': 'true', 'LIBXML2_VERSION': '2.8.0', 'LIBXSLT_VERSION': '1.1.28', 'LIBICONV_VERSION': '1.14'}
lxml_method = 'pip'
else:
lxml_options = None
lxml_method = 'pip'
URLS.update({
'PSYCOPG2': {'setup': 'psycopg2','url': 'http://www.psycopg.org/psycopg/tarballs/PSYCOPG-2-5/psycopg2-2.5.tar.gz', 'local':"psycopg2-2.5.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
'LXML': {'setup': 'lxml', 'url':"lxml-3.1.2.tar.gz", 'local':"lxml-3.1.2.tar.gz", 'install': {'method': lxml_method, 'option_str': None, 'dict_extra_env': lxml_options}},
})
class ResourcesEnv(object):
def __init__(self, src_base, urls, normal_installs):
self.src_base = src_base
self.URLS = {}
self.__init_url(urls)
self.NORMAL_INSTALL = normal_installs
def get_src_base_path(self, fpath):
return os.path.abspath(os.path.join(self.src_base, fpath)).replace("\\","/")
def __add_package_def(self, key, dict):
self.URLS[key] = dict
def __init_url(self, urls):
for key, url_dict in urls.items():
url_dict_copy = url_dict.copy()
if not url_dict['url'].startswith("http://"):
url_dict_copy['url'] = self.get_src_base_path(url_dict['url'])
url_dict_copy['local'] = self.get_src_base_path(url_dict['local'])
self.__add_package_def(key, url_dict_copy )
def ensure_dir(dir, logger):
if not os.path.exists(dir):
logger.notify('Creating directory %s' % dir)
os.makedirs(dir)
def extend_parser(parser):
parser.add_option(
'--index-url',
metavar='INDEX_URL',
dest='index_url',
default='http://pypi.python.org/simple/',
help='base URL of Python Package Index')
parser.add_option(
'--type-install',
metavar='type_install',
dest='type_install',
help='type install : local, url, setup - default : local')
parser.add_option(
'--ignore-packages',
metavar='ignore_packages',
dest='ignore_packages',
default=None,
help='list of comma separated keys for package to ignore')
def install_psycopg2(option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop):
psycopg2_src = os.path.join(src_dir,"psycopg2.zip")
shutil.copy(res_env.URLS['PSYCOPG2'][res_source_key], psycopg2_src)
#extract psycopg2
zf = zipfile.ZipFile(psycopg2_src)
psycopg2_base_path = os.path.join(src_dir,"psycopg2")
zf.extractall(psycopg2_base_path)
zf.close()
psycopg2_src_path = os.path.join(psycopg2_base_path, os.listdir(psycopg2_base_path)[0])
shutil.copytree(os.path.join(psycopg2_src_path, 'psycopg2'), os.path.abspath(os.path.join(home_dir, 'Lib/site-packages', 'psycopg2')))
shutil.copy(os.path.join(psycopg2_src_path, 'psycopg2-2.4.5-py2.7.egg-info'), os.path.abspath(os.path.join(home_dir, 'Lib/site-packages', 'site-packages')))
def install_mysql(option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop):
args = [os.path.abspath(os.path.join(home_dir, 'bin', 'pip')), 'install', res_env.URLS['MYSQL'][res_source_key]]
if option_str :
args.insert(4,option_str)
call_subprocess(args,
cwd=os.path.abspath(tmp_dir),
filter_stdout=filter_python_develop,
show_stdout=True,
extra_env=extra_env)
mysqlconfig_output = []
call_subprocess(['mysql_config', '--libmysqld-libs'],
cwd=os.path.abspath(tmp_dir),
filter_stdout=lambda line: mysqlconfig_output.append(line),
show_stdout=True)
mysqlconfig_output = "".join(mysqlconfig_output)
m = re.search("\-L[\'\"]?([\w\/]+)[\'\"]?", mysqlconfig_output)
if m:
repdylibpath = m.group(1)
else:
repdylibpath = '/usr/local/mysql/lib'
dyliblist = glob.glob(repdylibpath+"/libmysqlclient.*.dylib")
def key_func(s):
m = re.match(repdylibpath+"/libmysqlclient\.([\d]+)\.dylib", s)
if m:
return int(m.group(1))
else:
return sys.maxint
dyliblist.sort(key=key_func)
if dyliblist:
dylibpath = dyliblist[0]
else:
dylibpath = '/usr/local/mysql/lib/libmysqlclient.18.dylib'
dylibname = os.path.basename(dylibpath)
sopath = os.path.join(os.path.abspath(lib_dir), 'site-packages', '_mysql.so')
call_subprocess(['install_name_tool', '-change', dylibname, dylibpath, sopath],
cwd=os.path.abspath(tmp_dir),
filter_stdout=filter_python_develop,
show_stdout=True)
def gen_install_comp_lib(lib_name, lib_key, configure_options=[]):
def install_lib(option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop):
lib_src = os.path.join(src_dir,lib_name+".tar.gz")
shutil.copy(res_env.URLS[lib_key][res_source_key], lib_src)
tf = tarfile.open(lib_src,'r:gz')
lib_base_path = os.path.join(src_dir, lib_name)
logger.notify("Extract %s to %s " % (lib_name,lib_base_path))
tf.extractall(lib_base_path)
tf.close()
lib_src_path = os.path.join(lib_base_path, os.listdir(lib_base_path)[0])
logger.notify(libname + " configure")
call_subprocess(['configure', '--prefix='+os.path.abspath(home_dir)] + configure_options,
cwd=os.path.abspath(lib_src_path),
filter_stdout=filter_python_develop,
show_stdout=True)
logger.notify(libname + " make")
call_subprocess(['make'],
cwd=os.path.abspath(lib_src_path),
filter_stdout=filter_python_develop,
show_stdout=True)
logger.notify(libname + "make install")
call_subprocess(['make', 'install'],
cwd=os.path.abspath(lib_src_path),
filter_stdout=filter_python_develop,
show_stdout=True)
return install_lib
install_libjpeg = gen_install_comp_lib("libjpeg", "LIBJPEG", ['--enable-shared'])
install_zlib = gen_install_comp_lib("zlib", "ZLIB", [])
def lib_generate_install_methods(path_locations, src_base, Logger, call_subprocess, normal_installs, options_to_add=None, urls= None):
all_urls = URLS.copy()
if urls is not None:
all_urls.update(urls)
res_env = ResourcesEnv(src_base, all_urls, normal_installs)
def filter_python_develop(line):
if not line.strip():
return Logger.DEBUG
for prefix in ['Searching for', 'Reading ', 'Best match: ', 'Processing ',
'Moving ', 'Adding ', 'running ', 'writing ', 'Creating ',
'creating ', 'Copying ']:
if line.startswith(prefix):
return Logger.DEBUG
return Logger.NOTIFY
def normal_install(key, method, option_str, extra_env, res_source_key, home_dir, tmp_dir, res_env, logger, call_subprocess):
logger.notify("Install %s from %s with %s" % (key,res_env.URLS[key][res_source_key],method))
if method == 'pip':
if sys.platform == 'win32':
args = [os.path.abspath(os.path.join(home_dir, 'Scripts', 'pip')), 'install', res_env.URLS[key][res_source_key]]
else:
args = [os.path.abspath(os.path.join(home_dir, 'bin', 'pip')), 'install', res_env.URLS[key][res_source_key]]
if option_str :
args.insert(4,option_str)
call_subprocess(args,
cwd=os.path.abspath(tmp_dir),
filter_stdout=filter_python_develop,
show_stdout=True,
extra_env=extra_env)
else:
if sys.platform == 'win32':
args = [os.path.abspath(os.path.join(home_dir, 'Scripts', 'easy_install')), res_env.URLS[key][res_source_key]]
else:
args = [os.path.abspath(os.path.join(home_dir, 'bin', 'easy_install')), res_env.URLS[key][res_source_key]]
if option_str :
args.insert(1,option_str)
call_subprocess(args,
cwd=os.path.abspath(tmp_dir),
filter_stdout=filter_python_develop,
show_stdout=True,
extra_env=extra_env)
def after_install(options, home_dir):
global logger
verbosity = options.verbose - options.quiet
logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)])
home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
base_dir = os.path.dirname(home_dir)
src_dir = os.path.join(home_dir, 'src')
tmp_dir = os.path.join(home_dir, 'tmp')
ensure_dir(src_dir, logger)
ensure_dir(tmp_dir, logger)
system_str = platform.system()
res_source_key = getattr(options, 'type_install') if hasattr(options, 'type_install') else 'local' #.get('type_install', 'local')
if res_source_key is None:
res_source_key = local
ignore_packages = []
if system_str == 'Windows':
default_install_options = {'method': 'easy_install', 'option_str': None, 'dict_extra_env': None}
else:
default_install_options = {'method': 'pip', 'option_str': None, 'dict_extra_env': None}
if options.ignore_packages :
ignore_packages = options.ignore_packages.split(",")
logger.indent += 2
try:
for key in res_env.NORMAL_INSTALL:
if key not in res_env.URLS:
logger.notify("%s not found in def : passing" % (key,))
install_options = res_env.URLS[key].get('install', None)
if install_options is None:
install_options = default_install_options
method = install_options.get('method', default_install_options['method'])
option_str = install_options.get('option_str', default_install_options['option_str'])
extra_env = install_options.get('dict_extra_env', default_install_options['dict_extra_env'])
#isinstance(lst, (list, tuple))
if key not in ignore_packages:
if callable(method):
method(option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop)
elif method in globals() and callable(globals()[method]) and method not in ['pip', 'easy_install']:
globals()[method](option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop)
else:
normal_install(key, method, option_str, extra_env, res_source_key, home_dir, tmp_dir, res_env, logger, call_subprocess)
logger.notify("Clear source dir")
shutil.rmtree(src_dir)
finally:
logger.indent -= 2
script_dir = join(base_dir, bin_dir)
logger.notify('Run "%s Package" to install new packages that provide builds'
% join(script_dir, 'easy_install'))
def adjust_options(options, args):
if not options_to_add:
pass
for opt in options_to_add:
test_opt = opt.split('=',1)[0]
if not hasattr(options,test_opt) or getattr(options, test_opt) is None:
setattr(options, test_opt,opt.split('=',1)[1] if "=" in opt else True)
return adjust_options, extend_parser, after_install