pip の-rで渡すファイルの中でsourceの取得を使うことができるのだが、それをもっと賢く使えば良
かったかも。sh scriptがかけない人なので、なんでもpythonで書いちゃう、すべてが釘に見える人。しかも無駄(?)にきれい。本人は脳みそのキャパが小さいのでこのくらいきれいじゃないと死んじゃうんです。
いくつかポイント
- activateのコードを読んだ上で必要だと思われた、環境変数を待避してます。(でもスタックを作るのはやり過ぎだったかも。sub-Targetでなんかbuildするなら必要かもしれない。)
- subprocessを乱用してソースコードをかき集め、そこに含まれているfreeze.txtをみてpip installを行い、依存関係を解決する。
- build_procで指定した関数を実行して必要なものを生成。(rstからsphinxをつかってhtmlを生成)
virtualenvも環境を継承できればいいのになぁ、と思う。よくドキュメントを読んでいないせいかもしれない。ていうか、こういうどのpackageを使うかを管理する機能をpython自体に持たせてほしい。何回もgetされるとだるいので、cacheしてほしいし .i.e packageの実体とpackageがインストールされている事実を分離して(eggのdevとかできてるよな)、インストールされている事実だけをenvごとにもってほしいよね。
import os
import os.path
import subprocess
class VirtualEnv(object):
'''
VIRTUAL_ENV=/home/ubuntu/virtualenv/ci-proj
PATH=/home/ubuntu/virtualenv/ci-proj/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
PS1=(ci-proj)\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$
'''
_names = ('VIRTUAL_ENV', 'PATH', 'PS1',)
def __init__(self, **kws):
for n in self._names:
if n in kws:
self.__dict__.update({n: kws[n]})
def read(self):
for n in self._names:
self.__dict__.update({n: os.getenv(n)})
def __eq__(self, other):
for n in self._names:
if getattr(self, n) != getattr(other, n):
return False
return True
def activate(self):
'''
$ source ~/virtualenv/deploy/bin/activate
'''
for n in self._names:
os.environ[n]=getattr(self, n)
subprocess.call(['env'])
def deativate(self):
'''
$ deactivate
'''
# activate some thing else.
def __str__(self):
return ''%(id(self), ' '.join(['%s:%s'%(n, getattr(self, n)) for n in self._names]))
class EnvStack(object):
def __init__(self):
self._stack = []
v = self.get_current()
self._push(v)
self.check_invariant()
def check_invariant(self):
v = self.get_current()
u = self.top()
if v != u:
print v
print u
print self._stack
assert v==u
def close(self):
while self._stack > 1:
self.pop()
def get_current(self):
v = VirtualEnv()
v.read()
return v
def top(self):
return self._stack[-1]
def push(self, v):
self.check_invariant()
v.activate()
self._push(v)
self.check_invariant()
def _push(self, v):
self._stack.append(v)
def pop(self):
self.check_invariant()
self._stack.pop(-1)
v = self.top()
v.activate()
self.check_invariant()
class Target(object):
def __init__(self, src, branch, directory, dep=None, entrypoint=None, build_proc=None):
self.src = src
self.branch = branch
self.directory = directory
self.entrypoint = entrypoint
self.build_proc = build_proc
if dep:
self.dep = dep
else:
self.dep = tuple()
def mypath(self, builddir):
return os.path.join(builddir, self.directory)
def start_context(self, builddir):
self._cwd = os.getcwd()
os.chdir(self.mypath(builddir))
def end_context(self):
os.chdir(self._cwd)
def get(self, builddir):
subprocess.call(['git', 'clone', '-n', self.src, self.mypath(builddir)])
self.start_context(builddir)
subprocess.call(['git', 'checkout', self.branch])
self.end_context()
def pip(self, builddir):
self.start_context(builddir)
subprocess.call(['pip', 'install', '-r', 'freeze.txt'])
self.end_context()
def resolve(self, builddir):
for d in self.dep:
d.prepare(builddir)
t = os.path.join(os.getcwd(), builddir, d.directory, d.directory) #FIXME
self.symlink(builddir, t)
self.pip(builddir)
def build(self, builddir):
if self.build_proc:
self.start_context(builddir)
self.build_proc(self)
self.end_context()
def prepare(self, builddir):
self.get(builddir)
self.resolve(builddir)
self.build(builddir)
def symlink(self, builddir, target):
self.start_context(builddir)
subprocess.call(['ln', '-s', target])
self.end_context()
def run(self, builddir):
self.start_context(builddir)
subprocess.call(['python', self.entrypoint,])
self.end_context()
tonic = Target(
src='',
branch='migrate',
directory='tonic')
bglib = Target(
src='ひみつ',
branch='migration',
directory='bglib')
def build_doc(t):
os.chdir('doc')
subprocess.call(['make', 'html'])
imageserver = Target(
src='ひみつ',
branch='master',
directory='imageserver',
dep=(tonic, bglib),
entrypoint='sample.py',
build_proc=build_doc)
env = VirtualEnv(
VIRTUAL_ENV='/home/ubuntu/virtualenv/deploy',
PATH='/home/ubuntu/virtualenv/deploy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games',
PS1='(deploy)\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$',
)
#print env
s = EnvStack()
def deploy(builddir):
s.push(env)
os.mkdir(builddir)
imageserver.prepare(builddir)
s.pop()
def run(builddir):
s.push(env)
imageserver.run(builddir)
s.pop()
def clean(builddir):
subprocess.call(['rm', '-rf', builddir])
if __name__ == '__main__':
import sys
cmd = sys.argv[1]
print repr(cmd)
builddir = 'build'
if cmd=='run':
run(builddir)
elif cmd=='deploy':
deploy(builddir)
elif cmd=='clean':
clean(builddir)
else:
print 'unknown cmd', cmd
0 コメント:
コメントを投稿