Mercurial > hg > MakeItSo
comparison makeitso/makeitso.py @ 159:cfd4f1e91090
wip
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Tue, 30 Jul 2013 15:20:38 -0700 |
parents | 169e02e190ef |
children | 668b01d04457 |
comparison
equal
deleted
inserted
replaced
158:ff1f41a18da9 | 159:cfd4f1e91090 |
---|---|
88 return os.path.basename(uri) | 88 return os.path.basename(uri) |
89 | 89 |
90 def include(uri): | 90 def include(uri): |
91 f, headers = urllib.urlretrieve(uri) # XXX -> urllib2 for timeout | 91 f, headers = urllib.urlretrieve(uri) # XXX -> urllib2 for timeout |
92 return file(f).read() | 92 return file(f).read() |
93 | |
93 | 94 |
94 ### things that deal with variables | 95 ### things that deal with variables |
95 | 96 |
96 class MissingVariablesException(Exception): | 97 class MissingVariablesException(Exception): |
97 """exception for (non-interactive) missing variables""" | 98 """exception for (non-interactive) missing variables""" |
116 | 117 |
117 ### template classes | 118 ### template classes |
118 | 119 |
119 class ContentTemplate(tempita.Template): | 120 class ContentTemplate(tempita.Template): |
120 """MakeItSo's extension of tempita's Template class""" | 121 """MakeItSo's extension of tempita's Template class""" |
121 | 122 |
122 defaults = {'include': include} | 123 defaults = {'include': include} |
123 | 124 |
124 def __init__(self, content, name=None, interactive=True, variables=None): | 125 def __init__(self, content, name=None, interactive=True, variables=None): |
125 | 126 |
126 # default variables | 127 # default variables |
127 self.defaults = self.__class__.defaults.copy() | 128 self.defaults = self.__class__.defaults.copy() |
128 self.defaults.update(variables or {}) | 129 self.defaults.update(variables or {}) |
129 | 130 |
130 # TODO: automagically tell if the program is interactive or not | 131 # TODO: automagically tell if the program is interactive or not |
131 self.interactive = interactive | 132 self.interactive = interactive |
132 | 133 |
133 tempita.Template.__init__(self, content, name=name) | 134 tempita.Template.__init__(self, content, name=name) |
134 | 135 |
135 def get_variables(self, **variables): | 136 def get_variables(self, **variables): |
136 """the template's augmented variable set""" | 137 """the template's augmented variable set""" |
137 vars = self.defaults.copy() | 138 vars = self.defaults.copy() |
161 if missing: | 162 if missing: |
162 if self.interactive: | 163 if self.interactive: |
163 vars.update(self.read_variables(missing)) | 164 vars.update(self.read_variables(missing)) |
164 else: | 165 else: |
165 raise MissingVariablesException(missing) | 166 raise MissingVariablesException(missing) |
166 | 167 |
167 def variables(self): | 168 def variables(self): |
168 """return the variables needed for a template""" | 169 """return the variables needed for a template""" |
169 return self.missing() | 170 return self.missing() |
170 | 171 |
171 def substitute(self, **variables): | 172 def substitute(self, **variables): |
186 class URITemplate(ContentTemplate): | 187 class URITemplate(ContentTemplate): |
187 """template for a file or URL""" | 188 """template for a file or URL""" |
188 | 189 |
189 def __init__(self, uri, interactive=True, variables=None): | 190 def __init__(self, uri, interactive=True, variables=None): |
190 content = include(uri) | 191 content = include(uri) |
191 | 192 |
192 # remove makeitso shebang if it has one | 193 # remove makeitso shebang if it has one |
193 if shebang_re.match(content): | 194 if shebang_re.match(content): |
194 content = os.linesep.join(content.splitlines()[1:]) | 195 content = os.linesep.join(content.splitlines()[1:]) |
195 | 196 |
196 variables = variables or {} | 197 variables = variables or {} |
197 if 'here' not in variables: | 198 if 'here' not in variables: |
198 variables['here'] = parent_uri(uri) | 199 variables['here'] = parent_uri(uri) |
199 # TODO: could add other metadata about the uri, | 200 # TODO: could add other metadata about the uri, |
200 # such as last modification time' | 201 # such as last modification time' |
201 | 202 |
202 ContentTemplate.__init__(self, content, name=uri, | 203 ContentTemplate.__init__(self, content, name=uri, |
203 interactive=interactive, | 204 interactive=interactive, |
204 variables=variables) | 205 variables=variables) |
205 | 206 |
206 def substitute(self, variables, output=None): | 207 def substitute(self, variables, output=None): |
226 print >> output, content | 227 print >> output, content |
227 | 228 |
228 | 229 |
229 class DirectoryTemplate(ContentTemplate): | 230 class DirectoryTemplate(ContentTemplate): |
230 """template for a directory structure""" | 231 """template for a directory structure""" |
231 | 232 |
232 def __init__(self, directory, interactive=True, variables=None): | 233 def __init__(self, directory, interactive=True, variables=None): |
233 """ | 234 """ |
234 - output : output directory; if None will render in place | 235 - output : output directory; if None will render in place |
235 """ | 236 """ |
236 assert os.path.isdir(directory) | 237 assert os.path.isdir(directory) |
244 checks output for validity | 245 checks output for validity |
245 """ | 246 """ |
246 assert output # must provide output | 247 assert output # must provide output |
247 if os.path.exists(output): | 248 if os.path.exists(output): |
248 assert os.path.isdir(output), "%s: Must be a directory" % self.name | 249 assert os.path.isdir(output), "%s: Must be a directory" % self.name |
249 | 250 |
250 def missing(self, **variables): | 251 def missing(self, **variables): |
251 vars = self.defaults.copy() | 252 vars = self.defaults.copy() |
252 vars.update(variables) | 253 vars.update(variables) |
253 missing = set([]) | 254 missing = set([]) |
254 for dirpath, dirnames, filenames in os.walk(self.name): | 255 for dirpath, dirnames, filenames in os.walk(self.name): |
262 # find variables from files | 263 # find variables from files |
263 for f in filenames: | 264 for f in filenames: |
264 missed = ContentTemplate(f).missing(**vars) | 265 missed = ContentTemplate(f).missing(**vars) |
265 missing.update(missed) | 266 missing.update(missed) |
266 variables.update(dict([(i, '') for i in missed])) | 267 variables.update(dict([(i, '') for i in missed])) |
267 | 268 |
268 path = os.path.join(dirpath, f) | 269 path = os.path.join(dirpath, f) |
269 template = URITemplate(path, interactive=self.interactive) | 270 template = URITemplate(path, interactive=self.interactive) |
270 missed = template.missing(**vars) | 271 missed = template.missing(**vars) |
271 missing.update(missed) | 272 missing.update(missed) |
272 variables.update(dict([(i, '') for i in missed])) | 273 variables.update(dict([(i, '') for i in missed])) |
282 # per-directory control may be asserted | 283 # per-directory control may be asserted |
283 | 284 |
284 # make output directory if necessary | 285 # make output directory if necessary |
285 if output and not os.path.exists(output): | 286 if output and not os.path.exists(output): |
286 os.makedirs(output) | 287 os.makedirs(output) |
287 | 288 |
288 for dirname, dirnames, filenames in os.walk(self.name): | 289 for dirname, dirnames, filenames in os.walk(self.name): |
289 | 290 |
290 # interpolate directory names | 291 # interpolate directory names |
291 for d in dirnames: | 292 for d in dirnames: |
292 path = os.path.join(dirname, d) | 293 path = os.path.join(dirname, d) |
293 interpolated = ContentTemplate(path).substitute(**vars) | 294 interpolated = ContentTemplate(path).substitute(**vars) |
294 target = os.path.join(output, interpolated.split(self.name, 1)[-1].strip(os.path.sep)) | 295 target = os.path.join(output, interpolated.split(self.name, 1)[-1].strip(os.path.sep)) |
295 | 296 |
296 if os.path.exists(target): | 297 if os.path.exists(target): |
297 # ensure its a directory | 298 # ensure its a directory |
298 # TODO: check this first before interpolation is in progress | 299 # TODO: check this first before interpolation is in progress |
299 assert os.path.isdir(target), "Can't substitute a directory on top of the file" | 300 assert os.path.isdir(target), "Can't substitute a directory on top of the file" |
300 else: | 301 else: |