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 件のコメント:
コメントを投稿