Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(810)

Side by Side Diff: tools/testing/legpad/legpad.py

Issue 16123006: Remove unused files. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/testing/legpad/legpad.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2
3 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
4 # for details. All rights reserved. Use of this source code is governed by a
5 # BSD-style license that can be found in the LICENSE file.
6
7 """
8 Legpad is used to compile .dart files to javascript, using the dart2js compiler.
9
10 This is accomplished by creating an html file (usually called
11 <something>.legpad.html) that executes the dart2js compiler when the page
12 is loaded by a web browser (or DumpRenderTree).
13
14 The <something>.legpad.html file contains:
15
16 1. all the dart files that compose a user's dart program
17 2. all the dart files of dart:core and other standard dart libraries
18 (or any other symbol that can follow "dart:" in an import statement
19 3. legpad.dart (compiled to javascript)
20
21 The contents of each dart file is placed in a separate <script> tag.
22
23 When the html page is loaded by a browser, the leg compiler is invoked
24 and the dart program is compiled to javascript. The generated javascript is
25 placed in a <pre> element with id "output".
26
27 When the html page is passed to DumpRenderTree, the dumped output will
28 have the generated javascript.
29
30 See 'example.sh' for an example of how to run legpad.
31 """
32
33 import logging
34 import optparse
35 import os.path
36 import platform
37 import re
38 import subprocess
39 import sys
40
41
42 class FileNotFoundException(Exception):
43 def __init__(self, file_name):
44 self._name = file_name
45
46 def __str__(self):
47 return self._name
48
49
50 class CommandFailedException(Exception):
51 def __init__(self, message):
52 self._message = message
53
54 def GetMessage(self):
55 return self._message
56
57
58 # Template for the legpad.html page we're going to generate.
59 HTML = """<!DOCTYPE html>
60 <html>
61 <head>
62 <style type="text/css">
63 textarea {
64 width: 100%;
65 height: 200px;
66 }
67 .label {
68 margin-top: 5px;
69 }
70 pre {
71 border: 2px solid black;
72 }
73 </style>
74 {{script_tags}}
75 <script type="text/javascript">
76 if (window.layoutTestController) {
77 layoutTestController.dumpAsText();
78 }
79 </script>
80 </head>
81 <body>
82 <h1>Legpad</h1>
83 <div class="label">Input:</div>
84 <textarea id="input"></textarea>
85 <div class="label">Compiler Messages:</div>
86 <pre id="warnings"></pre>
87 <div class="label">Timing:</div>
88 <pre id="timing"></pre>
89 <div class="label">Output:</div>
90 <pre id="output"></pre>
91 <script type="text/javascript">
92 {{LEGPAD_JS}}
93 </script>
94 </body>
95 </html>
96 """
97
98 # This finds everything after the word "Output:" in the html page.
99 # (Note, because the javascript we're fishing out spans multiple lines
100 # we need to use the DOTALL switch here.)
101 OUTPUT_JAVASCRIPT_REGEX = re.compile(".*\nOutput:\n(.*)\n#EOF", re.DOTALL)
102
103 # If the legpad.dart encounters a compilation error, the generated
104 # javascript will contains the words "dart2js compilation error".
105 COMPILATION_ERROR_REGEX = re.compile(".*dart2js compilation error.*", re.DOTALL)
106
107 # We use "application/inert" here to make the browser ignore the
108 # these script tags. (legpad.dart will fish out the contents as needed.)
109 #
110 SCRIPT_TAG = """<script type="application/inert" id="{{id}}">
111 {{contents}}
112 </script>
113 """
114
115 # Regex that finds #import, #source and #native directives in .dart files.
116 # match.group(1) = "import", "source" or "native"
117 # match.group(2) = url of file being imported
118 DIRECTIVE_RE = re.compile(r"^#(import|source|native)\([\"']([^\"']*)[\"']")
119
120 # id of script tag that holds name of the top dart file to be compiled,
121 # (This file name passed will be passed to the leg compiler by legpad.dart.)
122 MAIN_ID = "main_id"
123
124 # TODO(mattsh): read this from some config file once ahe/zundel create it
125 DART_LIBRARIES = {
126 "core": "lib/compiler/implementation/lib/core.dart",
127 "_js_helper": "lib/compiler/implementation/lib/js_helper.dart",
128 "_interceptors": "lib/compiler/implementation/lib/interceptors.dart",
129 "dom": "lib/dom/frog/dom_frog.dart",
130 "html": "lib/html/frog/html_frog.dart",
131 "io": "lib/compiler/implementation/lib/io.dart",
132 "isolate": "lib/isolate/isolate_leg.dart",
133 "json": "lib/json/json.dart",
134 "uri": "lib/uri/uri.dart",
135 "utf": "lib/utf/utf.dart",
136 }
137
138 class Pad(object):
139 """
140 Accumulates all source files that are needed to compile a dart program,
141 and places them in <script> tags on an html page.
142 """
143
144 def __init__(self, argv):
145 parser = optparse.OptionParser(usage=
146 "%prog [options] file_to_compile.dart"
147 )
148 parser.add_option("-o", "--out",
149 help="name of javascript output file")
150 parser.add_option("-v", "--verbose", action="store_true",
151 help="more verbose logging")
152 (options, args) = parser.parse_args(argv)
153
154 log_level = logging.INFO
155 if options.verbose:
156 log_level = logging.DEBUG
157 logging.basicConfig(level=log_level)
158
159 if len(args) < 2:
160 parser.print_help()
161 sys.exit(1)
162
163 self.main_file = os.path.abspath(args[1])
164
165 # directory of this script
166 self.legpad_dir = os.path.abspath(os.path.dirname(argv[0]))
167
168 # root of dart source repo
169 self.dart_dir = os.path.dirname(os.path.dirname(os.path.dirname(
170 self.legpad_dir)))
171
172 logging.debug("dart_dir: '%s'" % self.dart_dir)
173
174 if options.out:
175 # user has specified an output file name
176 self.js_file = os.path.abspath(options.out)
177 else:
178 # User didn't specify an output file, so use the input
179 # file name as the base of the output file name.
180 self.js_file = self.main_file + ".legpad.js"
181
182 logging.debug("js_file: '%s" % self.js_file)
183
184 # this is the html file that we pass to DumpRenderTree
185 self.html_file = self.main_file + ".legpad.html"
186 logging.debug("html_file: '%s'" % self.html_file)
187
188 # map from file name to File object (contains entries for all corelib
189 # and all other dart files needed to compile main_file)
190 self.name_to_file = {}
191
192 # map from script tag id to File object
193 self.id_to_file = {}
194
195 self.load_libraries()
196 self.load_file(self.main_file)
197
198 html = self.generate_html()
199 write_file(self.html_file, html)
200
201 js = self.generate_js()
202 write_file(self.js_file, js)
203
204 line_count = len(js.splitlines())
205 logging.debug("generated '%s' (%d lines)", self.js_file, line_count)
206
207 match = COMPILATION_ERROR_REGEX.match(js)
208 if match:
209 sys.exit(1)
210
211 def generate_html(self):
212 tags = []
213 for f in self.id_to_file.values():
214 tags.append(self._create_tag(f.id, f.contents))
215 tags.append(self._create_tag(MAIN_ID, self.shorten(self.main_file)))
216 html = HTML.replace("{{script_tags}}", "".join(tags))
217
218 legpad_js = os.path.join(self.legpad_dir, "legpad.dart.js")
219 check_exists(legpad_js)
220
221 html = html.replace("{{LEGPAD_JS}}", read_file(legpad_js))
222 return html
223
224 def generate_js(self):
225 drt = os.path.join(self.dart_dir, "client/tests/drt/DumpRenderTree")
226 if platform.system() == 'Darwin':
227 drt += ".app"
228 elif platform.system() == 'Windows':
229 raise Exception("legpad does not run on Windows")
230
231 check_exists(drt)
232 args = []
233 args.append(drt)
234 args.append(self.html_file)
235
236 stdout = run_command(args)
237 match = OUTPUT_JAVASCRIPT_REGEX.match(stdout)
238 if not match:
239 raise Exception("can't find regex in DumpRenderTree output")
240 return match.group(1)
241
242 @staticmethod
243 def _create_tag(id, contents):
244 s = SCRIPT_TAG
245 s = s.replace("{{id}}", id)
246 # TODO(mattsh) - need to html escape here
247 s = s.replace("{{contents}}", contents)
248 return s
249
250 def dart_library(self, name):
251 path = DART_LIBRARIES[name]
252 if not path:
253 raise Exception("unrecognized 'dart:%s'", name)
254 return os.path.join(self.dart_dir, path)
255
256 def load_libraries(self):
257 for name in DART_LIBRARIES:
258 self.load_file(self.dart_library(name))
259
260 def load_file(self, name):
261 name = os.path.abspath(name)
262 if name in self.name_to_file:
263 return
264 f = File(self, name)
265 self.name_to_file[f.name] = f
266 if f.id in self.id_to_file:
267 raise Exception("ambiguous id '%s'" % f.id)
268 self.id_to_file[f.id] = f
269 f.directives()
270
271 def shorten(self, name):
272 """
273 Change that full path of the dart svn repo to simply "dartdir"
274 """
275 return name.replace(self.dart_dir, "dartdir")
276
277 def make_id(self, name):
278 """
279 Generates an id (based on the file name) for the <script> tag that will
280 hold the contents of this file.
281 """
282 return self.shorten(name).replace("/", "_").replace(".", "_")
283
284
285 class File(object):
286 def __init__(self, pad, name):
287 self.pad = pad
288 self.name = name
289 self.id = pad.make_id(name)
290 self.contents = read_file(name)
291
292 def directives(self):
293 """Load files referenced by #source, #import and #native directives."""
294 lines = self.contents.split("\n")
295 self.line_number = 0
296 for line in lines:
297 self.line_number += 1
298 self._directive(line)
299
300 def _directive(self, line):
301 match = DIRECTIVE_RE.match(line)
302 if not match:
303 return
304 url = match.group(2)
305 if url.startswith("dart:"):
306 path = self.pad.dart_library(url[len("dart:"):])
307 else:
308 path = os.path.join(os.path.dirname(self.name), url)
309 self.pad.load_file(path)
310
311
312 def read_file(file_name):
313 check_exists(file_name)
314 with open(file_name, "r") as input:
315 contents = input.read()
316 logging.debug("read_file '%s' (%d bytes)" % (file_name, len(contents)))
317 return contents
318
319
320 def write_file(file_name, contents):
321 with open(file_name, "w") as output:
322 output.write(contents)
323
324 check_exists(file_name)
325 logging.debug("write_file '%s' (%d bytes)" % (file_name, len(contents)))
326
327
328 def check_exists(file_name):
329 if not os.path.exists(file_name):
330 raise FileNotFoundException(file_name)
331
332
333 def format_command(args):
334 return ' '.join(args)
335
336
337 def run_command(args):
338 """
339 Args:
340 command: comamnd with arguments to exec
341 Returns:
342 all output that this command sent to stdout
343 """
344
345 command = format_command(args)
346 logging.info("RUNNING: '%s'" % command)
347 child = subprocess.Popen(args,
348 stdout=subprocess.PIPE,
349 stderr=subprocess.PIPE,
350 close_fds=True)
351 (stdout, stderr) = child.communicate()
352 exit_code = child.wait()
353 if exit_code:
354 for line in stderr.splitlines():
355 logging.info(line)
356 msg = "FAILURE (exit_code=%d): '%s'" % (exit_code, command)
357 logging.error(msg)
358 raise CommandFailedException(msg)
359 logging.debug("SUCCEEDED (%d bytes)" % len(stdout))
360 return stdout
361
362
363 def main(argv):
364 Pad(argv)
365
366 if __name__ == "__main__":
367 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « tools/testing/legpad/legpad.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698