Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | |
|
Ryan Tseng
2015/06/09 23:03:05
I think i'd prefer a filename.template file with a
| |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 import argparse | |
| 6 import datetime | |
| 7 import os | |
| 8 import sys | |
| 9 import textwrap | |
| 10 | |
| 11 # infra subdirectory containing tools. | |
| 12 TOOL_DIR = os.path.dirname(os.path.dirname(__file__)) | |
| 13 | |
| 14 | |
| 15 COPYRIGHT_NOTICE = """\ | |
| 16 # Copyright %s The Chromium Authors. All rights reserved. | |
| 17 # Use of this source code is governed by a BSD-style license that can be | |
| 18 # found in the LICENSE file. | |
| 19 """ % datetime.datetime.now().strftime('%Y') | |
| 20 | |
| 21 | |
| 22 def add_argparse_options(parser): | |
| 23 parser.add_argument( | |
| 24 'name', metavar='name', type=str, nargs=1, | |
| 25 help='The name of the new tool.') | |
| 26 | |
| 27 parser.add_argument('--base-dir', default=TOOL_DIR, | |
| 28 help='Directory where to create the tool. Default: ' | |
| 29 '%(default)s') | |
| 30 | |
| 31 | |
| 32 def generate_init_file(dirpath): | |
| 33 """Generate a __init__.py file in the specified directory.""" | |
| 34 | |
| 35 init_file_path = os.path.join(dirpath, '__init__.py') | |
| 36 if os.path.isfile(init_file_path): | |
| 37 print 'Skipping existing file %s' % init_file_path | |
| 38 return | |
| 39 | |
| 40 with open(init_file_path, 'w') as f: | |
| 41 f.write(COPYRIGHT_NOTICE) | |
| 42 | |
| 43 | |
| 44 def generate_main_file(dirpath, toolname): | |
| 45 """Generate a __main__.py file in the specified directory.""" | |
| 46 main_file_path = os.path.join(dirpath, '__main__.py') | |
| 47 if os.path.isfile(main_file_path): | |
| 48 print 'Skipping existing file %s' % main_file_path | |
| 49 return | |
| 50 | |
| 51 MAIN_CONTENT = textwrap.dedent(""" | |
| 52 \"\"\"<General description of {Toolname} here.> | |
| 53 | |
| 54 [TBD] Example invocation: | |
| 55 ./run.py infra.tools.{toolname} <arguments> | |
| 56 \"\"\" | |
| 57 | |
| 58 # This file is untested, keep as little code as possible in there. | |
| 59 | |
| 60 import argparse | |
| 61 import logging | |
| 62 import sys | |
| 63 | |
| 64 from infra.tools.{toolname} import {toolname} | |
| 65 import infra_libs.logs | |
| 66 | |
| 67 | |
| 68 # https://storage.googleapis.com/chromium-infra-docs/infra/html/logging.html | |
| 69 LOGGER = logging.getLogger(__name__) | |
| 70 | |
| 71 | |
| 72 def main(argv): | |
| 73 parser = argparse.ArgumentParser( | |
| 74 prog="{toolname}", | |
| 75 description=sys.modules['__main__'].__doc__) | |
| 76 {toolname}.add_argparse_options(parser) | |
| 77 infra_libs.logs.add_argparse_options(parser) | |
| 78 _args = parser.parse_args(argv) | |
| 79 | |
| 80 infra_libs.logs.process_argparse_options(parser) | |
| 81 | |
| 82 # Do more processing here | |
| 83 LOGGER.info('{Toolname} starting.') | |
| 84 | |
| 85 | |
| 86 if __name__ == '__main__': | |
| 87 sys.exit(main(sys.argv[1:])) | |
| 88 """).format(toolname=toolname, Toolname=toolname.capitalize()) | |
| 89 | |
| 90 with open(main_file_path, 'w') as f: | |
| 91 f.write(COPYRIGHT_NOTICE) | |
| 92 f.write(MAIN_CONTENT) | |
| 93 | |
| 94 | |
| 95 def generate_tool_file(dirpath, toolname): | |
| 96 """Generate a <toolname>.py file in the specified directory""" | |
| 97 | |
| 98 file_path = os.path.join(dirpath, '%s.py' % toolname) | |
| 99 if os.path.isfile(file_path): | |
| 100 print 'Skipping existing file %s' % file_path | |
| 101 return | |
| 102 | |
| 103 MODULE_CONTENT = textwrap.dedent(""" | |
| 104 \"\"\"Testable functions for {Toolname}.\"\"\" | |
| 105 | |
| 106 import logging | |
| 107 | |
| 108 | |
| 109 # https://storage.googleapis.com/chromium-infra-docs/infra/html/logging.html | |
| 110 LOGGER = logging.getLogger(__name__) | |
| 111 | |
| 112 | |
| 113 def add_argparse_options(parser): | |
| 114 \"\"\"Define command-line arguments.\"\"\" | |
| 115 parser.add_argument('--my-argument', '-m', help='') | |
| 116 """).format(Toolname=toolname.capitalize()) | |
| 117 | |
| 118 with open(file_path, 'w') as f: | |
| 119 f.write(COPYRIGHT_NOTICE) | |
| 120 f.write(MODULE_CONTENT) | |
| 121 | |
| 122 | |
| 123 def generate_test_file(dirpath, toolname, tested_file): | |
| 124 """Generate a test file in the proper place. | |
| 125 | |
| 126 Example: | |
| 127 generate_test_file('foo', 'bar') creates foo/test/bar_test.py | |
| 128 """ | |
| 129 file_path = os.path.join(dirpath, 'test', '%s_test.py' % tested_file) | |
| 130 if os.path.isfile(file_path): | |
| 131 print 'Skipping existing file %s' % file_path | |
| 132 return | |
| 133 | |
| 134 test_dir = os.path.join(dirpath, 'test') | |
| 135 if not os.path.exists(test_dir): | |
| 136 os.mkdir(os.path.join(test_dir)) | |
| 137 | |
| 138 MODULE_CONTENT = textwrap.dedent(""" | |
| 139 \"\"\"Tests for ../{tested_file}.py\"\"\" | |
| 140 | |
| 141 import argparse | |
| 142 import unittest | |
| 143 | |
| 144 from infra.tools.{toolname} import {tested_file} | |
| 145 | |
| 146 class MyTest(unittest.TestCase): | |
| 147 def test_arguments(self): | |
| 148 parser = argparse.ArgumentParser() | |
| 149 {tested_file}.add_argparse_options(parser) | |
| 150 args = parser.parse_args(['--my-argument', 'value']) | |
| 151 self.assertEqual(args.my_argument, 'value') | |
| 152 | |
| 153 ## expect_tests style: the test method returns a value (expectation) | |
| 154 ## that is stored when run in 'train' mode, and compared to in 'test' mode. | |
| 155 ## If the stored and returned values do not match, the test fails. | |
| 156 ## | |
| 157 ## def test_my_first_test_with_expectation(self): | |
| 158 ## # Use hash() here to make sure the test fails in any case. | |
| 159 ## return hash(MyTest) | |
|
Sergey Berezin
2015/06/10 00:32:37
nit: this looks confusing to me. Why would I want
| |
| 160 """).format(toolname=toolname, tested_file=tested_file) | |
| 161 | |
| 162 with open(file_path, 'w') as f: | |
| 163 f.write(COPYRIGHT_NOTICE) | |
| 164 f.write(MODULE_CONTENT) | |
| 165 | |
| 166 | |
| 167 def generate_tool_files(name, base_dir): | |
| 168 """Generate a stub tool from template files. | |
| 169 | |
| 170 Args: | |
| 171 name (str): name of the tool. This is also the name of the directory | |
| 172 generated. | |
| 173 base_dir (str): path to the directory where to create the files. | |
| 174 | |
| 175 Return: | |
| 176 tool_path (str or None): directory created or None is nothing has been done. | |
| 177 """ | |
| 178 | |
| 179 if not os.path.isdir(base_dir): | |
| 180 print 'Destination directory does not exist' | |
| 181 return 1 | |
| 182 | |
| 183 tool_dir = os.path.join(base_dir, name) | |
| 184 if os.path.exists(tool_dir): | |
| 185 print 'Tool seems to already exists: %s\nAborting.' % tool_dir | |
| 186 return 1 | |
| 187 | |
| 188 print 'Generating %s...' % tool_dir | |
| 189 os.mkdir(tool_dir) | |
| 190 generate_init_file(tool_dir) | |
| 191 generate_main_file(tool_dir, name) | |
| 192 generate_tool_file(tool_dir, name) | |
| 193 generate_test_file(tool_dir, name, name) | |
| 194 generate_init_file(os.path.join(tool_dir, 'test')) | |
| 195 print 'Done.' | |
| OLD | NEW |