diff options
Diffstat (limited to 'lib/dodai/build/__init__.py')
-rw-r--r-- | lib/dodai/build/__init__.py | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/lib/dodai/build/__init__.py b/lib/dodai/build/__init__.py new file mode 100644 index 0000000..c4989be --- /dev/null +++ b/lib/dodai/build/__init__.py | |||
@@ -0,0 +1,216 @@ | |||
1 | from setuptools.command.easy_install import easy_install | ||
2 | from distutils.util import convert_path | ||
3 | from pkg_resources import Distribution, PathMetadata, normalize_path | ||
4 | from distutils import log | ||
5 | from distutils.errors import * | ||
6 | import sys, os, setuptools, glob | ||
7 | import virtualenv | ||
8 | import textwrap | ||
9 | import tempfile | ||
10 | import subprocess | ||
11 | import stat | ||
12 | import pprint | ||
13 | |||
14 | |||
15 | |||
16 | class Filler(object): | ||
17 | |||
18 | TAB_WIDTH = 4 | ||
19 | TAB_CHAR = ' ' | ||
20 | LINE_LEN = 79 | ||
21 | |||
22 | def __init__(self, indent): | ||
23 | self._obj = None | ||
24 | self.initial_indent = self.TAB_CHAR*self.TAB_WIDTH*indent | ||
25 | indent+=1 | ||
26 | self.subsequent_indent = self.TAB_CHAR*self.TAB_WIDTH*indent | ||
27 | |||
28 | def __call__(self, text): | ||
29 | text = text.rstrip() | ||
30 | return self.process(text) | ||
31 | |||
32 | @property | ||
33 | def obj(self): | ||
34 | if not self._obj: | ||
35 | self._obj = textwrap.TextWrapper( | ||
36 | width=self.LINE_LEN, | ||
37 | initial_indent=self.initial_indent, | ||
38 | subsequent_indent=self.subsequent_indent, | ||
39 | ) | ||
40 | return self._obj.fill | ||
41 | |||
42 | def process(self, text): | ||
43 | out = [] | ||
44 | text = textwrap.dedent(text) | ||
45 | obj = self.obj | ||
46 | lines = text.split('\n') | ||
47 | for line in lines: | ||
48 | out.append(self.obj(line)) | ||
49 | return '\n'.join(out) | ||
50 | |||
51 | |||
52 | class AfterInstallActionBase(object): | ||
53 | |||
54 | def _quote_list(self, data): | ||
55 | if isinstance(data, basestring): | ||
56 | out = ["'{0}'".format(data)] | ||
57 | else: | ||
58 | out = ["'{0}'".format(d) for d in data] | ||
59 | return ', '.join(out) | ||
60 | |||
61 | class EasyInstall(AfterInstallActionBase): | ||
62 | |||
63 | CODE = """ | ||
64 | for package in [{packages}]: | ||
65 | easy_install(package) | ||
66 | """ | ||
67 | |||
68 | def __init__(self, packages): | ||
69 | self.packages = self._quote_list(packages) | ||
70 | self.fill = Filler(1) | ||
71 | |||
72 | def __call__(self): | ||
73 | code = self.CODE.format(packages=self.packages) | ||
74 | return self.fill(code) | ||
75 | |||
76 | |||
77 | class HgClone(AfterInstallActionBase): | ||
78 | |||
79 | CODE = """ | ||
80 | hg_clone('{url}', '{dest}') | ||
81 | """ | ||
82 | |||
83 | def __init__(self, url, dest): | ||
84 | self.url = url | ||
85 | self.dest = dest | ||
86 | self.fill = Filler(1) | ||
87 | |||
88 | def __call__(self): | ||
89 | code = self.CODE.format(url=self.url, dest=self.dest) | ||
90 | return self.fill(code) | ||
91 | |||
92 | |||
93 | class RunSetupCommand(AfterInstallActionBase): | ||
94 | |||
95 | CODE = """ | ||
96 | for dir in [{dirs}]: | ||
97 | setup_py(dir, {command}) | ||
98 | """ | ||
99 | |||
100 | def __init__(self, dirs, command): | ||
101 | self.dirs = self._quote_list(dirs) | ||
102 | self.command = repr(command).strip('[]()') | ||
103 | self.fill = Filler(1) | ||
104 | |||
105 | def __call__(self): | ||
106 | code = self.CODE.format(dirs=self.dirs, command=self.command) | ||
107 | return self.fill(code) | ||
108 | |||
109 | |||
110 | class RunPythonPrograms(AfterInstallActionBase): | ||
111 | |||
112 | CODE = """ | ||
113 | for program in [{programs}]: | ||
114 | run_program(program) | ||
115 | """ | ||
116 | |||
117 | def __init__(self, programs): | ||
118 | self.programs = self._quote_list(programs) | ||
119 | self.fill = Filler(1) | ||
120 | |||
121 | def __call__(self): | ||
122 | code = self.CODE.format(programs=self.programs) | ||
123 | return self.fill(code) | ||
124 | |||
125 | |||
126 | class AfterInstall(object): | ||
127 | |||
128 | FILE = 'after_install.py' | ||
129 | |||
130 | CODE = ''' | ||
131 | def after_install(options, home_dir): | ||
132 | paths = build_paths(home_dir) | ||
133 | easy_install = EasyInstall(paths) | ||
134 | hg_clone = HgClone(paths) | ||
135 | setup_py = SetupPy(paths) | ||
136 | run_program = RunPythonProgram(paths) | ||
137 | ''' | ||
138 | def __init__(self): | ||
139 | self.fill = Filler(0) | ||
140 | self._code_from_file_ = None | ||
141 | |||
142 | @property | ||
143 | def _code_from_file(self): | ||
144 | if not self._code_from_file_: | ||
145 | path = os.path.dirname(os.path.realpath(__file__)) | ||
146 | path = os.path.join(path, self.FILE) | ||
147 | fp = open(path, 'r') | ||
148 | self._code_from_file_ = fp.read() | ||
149 | fp.close() | ||
150 | return self._code_from_file_ | ||
151 | |||
152 | def __call__(self, chain): | ||
153 | out = [self._code_from_file, self.fill(self.CODE)] | ||
154 | for obj in chain: | ||
155 | out.append(obj()) | ||
156 | out = ''.join(out) | ||
157 | return out | ||
158 | |||
159 | |||
160 | class VirtualEnvDev(object): | ||
161 | |||
162 | NAME = 'devstrap.py' | ||
163 | PACKAGES = ['nose', 'virtualenv', 'ipython', 'mercurial', 'pylint'] | ||
164 | HG_URL = 'hg clone https://dodai.googlecode.com/hg' | ||
165 | HG_DEST = 'src' | ||
166 | AFTER_BUILD = [] | ||
167 | |||
168 | def __init__(self, path, name): | ||
169 | self.name = '{0}-{1}'.format(name, self.NAME) | ||
170 | self.path = os.path.join(path, self.name) | ||
171 | |||
172 | def __call__(self): | ||
173 | self._write() | ||
174 | print "File Built: {0}".format(self.path) | ||
175 | |||
176 | def _write(self): | ||
177 | with open(self.path, 'w') as f: | ||
178 | f.write(self._data) | ||
179 | |||
180 | @property | ||
181 | def _after_install(self): | ||
182 | chain = [ | ||
183 | EasyInstall(self.PACKAGES), | ||
184 | HgClone(self.HG_URL, self.HG_DEST), | ||
185 | RunSetupCommand(self.HG_DEST, 'develop'), | ||
186 | RunPythonPrograms(self.AFTER_BUILD) | ||
187 | ] | ||
188 | obj = AfterInstall() | ||
189 | return obj(chain) | ||
190 | |||
191 | @property | ||
192 | def _data(self): | ||
193 | return virtualenv.create_bootstrap_script(self._after_install) | ||
194 | |||
195 | |||
196 | class devstrap(easy_install): | ||
197 | |||
198 | description = 'create a devstrap file used for installing a dev env' | ||
199 | |||
200 | user_options = easy_install.user_options | ||
201 | boolean_options = easy_install.boolean_options | ||
202 | command_consumes_arguments = False | ||
203 | |||
204 | def run(self): | ||
205 | virtual_env = VirtualEnvDev(self.prefix, self.distribution.get_name()) | ||
206 | virtual_env() | ||
207 | |||
208 | def initialize_options(self): | ||
209 | easy_install.initialize_options(self) | ||
210 | |||
211 | def finalize_options(self): | ||
212 | if self.prefix: | ||
213 | if not os.path.exists(self.prefix): | ||
214 | os.makedirs(self.prefix) | ||
215 | else: | ||
216 | self.prefix = os.getcwd() | ||