From dbebb8d4395b68f452c313f783078e6ec1152825 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Sat, 4 Nov 2017 11:56:49 -0200 Subject: [PATCH 01/24] Option: "grumpc -output" to produce to a file --- tools/grumpc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/grumpc b/tools/grumpc index 53837738..6c56c739 100755 --- a/tools/grumpc +++ b/tools/grumpc @@ -34,6 +34,7 @@ from grumpy import pythonparser parser = argparse.ArgumentParser() parser.add_argument('script', help='Python source filename') parser.add_argument('-modname', default='__main__', help='Python module name') +parser.add_argument('-output', default=None, help='Golang output file path (defaults to stdout)') def main(args): @@ -56,6 +57,11 @@ def main(args): e.filename, e.lineno, e.text) return 2 + if args.output: + go_result = open(args.output, 'w') + else: + go_result = sys.stdout + # Do a pass for compiler directives from `from __future__ import *` statements try: future_node, future_features = imputil.parse_future_features(mod) @@ -78,7 +84,7 @@ def main(args): print >> sys.stderr, str(e) return 2 - writer = util.Writer(sys.stdout) + writer = util.Writer(go_result) tmpl = textwrap.dedent("""\ package $package import πg "grumpy" From 7b1dcb0ba9c6c0fb99d3a1081c75353d5ea3e3f0 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Sat, 4 Nov 2017 16:36:44 -0200 Subject: [PATCH 02/24] genmake._PrintRule got echo_debug=False Spits an @echo on the makefile if echo_debug=True --- tools/genmake | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/genmake b/tools/genmake index c13465a5..21d35018 100755 --- a/tools/genmake +++ b/tools/genmake @@ -28,11 +28,13 @@ parser.add_argument('-all_target', default='all', help='make target that will build all modules') -def _PrintRule(target, prereqs, rules): +def _PrintRule(target, prereqs, rules, echo_debug=False): print '{}: {}'.format(target, ' '.join(prereqs)) if rules: print '\t@mkdir -p $(@D)' for rule in rules: + if echo_debug: + print '\t@echo @{}'.format(rule) print '\t@{}'.format(rule) print @@ -69,7 +71,9 @@ def main(args): go_file = os.path.join(pydir, basename, 'module.go') _PrintRule(go_file, [os.path.join(dirpath, filename)], - ['grumpc -modname={} $< > $@'.format(modname)]) + ['grumpc -modname={} $< > $@'.format(modname)], + echo_debug=True) + recipe = (r"""pydeps -modname=%s $< | awk '{gsub(/\./, "/", $$0); """ r"""print "%s: %s/__python__/" $$0 ".a"}' > $@""") dep_file = os.path.join(pydir, basename, 'module.d') From 63fe42e4d183ac9e58c09079e896f744bceb49ed Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Mon, 6 Nov 2017 19:29:07 -0200 Subject: [PATCH 03/24] Refactor grumpc to ease legibility --- tools/grumpc | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/tools/grumpc b/tools/grumpc index 6c56c739..ad5cc8a3 100755 --- a/tools/grumpc +++ b/tools/grumpc @@ -23,6 +23,7 @@ import argparse import os import sys import textwrap +from StringIO import StringIO from grumpy.compiler import block from grumpy.compiler import imputil @@ -50,21 +51,17 @@ def main(args): with open(args.script) as py_file: py_contents = py_file.read() + try: - mod = pythonparser.parse(py_contents) + parsed_module = pythonparser.parse(py_contents) except SyntaxError as e: print >> sys.stderr, '{}: line {}: invalid syntax: {}'.format( e.filename, e.lineno, e.text) return 2 - if args.output: - go_result = open(args.output, 'w') - else: - go_result = sys.stdout - # Do a pass for compiler directives from `from __future__ import *` statements try: - future_node, future_features = imputil.parse_future_features(mod) + future_node, future_features = imputil.parse_future_features(parsed_module) except util.CompileError as e: print >> sys.stderr, str(e) return 2 @@ -72,18 +69,19 @@ def main(args): importer = imputil.Importer(gopath, args.modname, args.script, future_features.absolute_import) full_package_name = args.modname.replace('.', '/') - mod_block = block.ModuleBlock(importer, full_package_name, args.script, - py_contents, future_features) + module_block = block.ModuleBlock(importer, full_package_name, args.script, + py_contents, future_features) - visitor = stmt.StatementVisitor(mod_block, future_node) + visitor = stmt.StatementVisitor(module_block, future_node) # Indent so that the module body is aligned with the goto labels. with visitor.writer.indent_block(): try: - visitor.visit(mod) + visitor.visit(parsed_module) except util.ParseError as e: print >> sys.stderr, str(e) return 2 + go_result = StringIO() writer = util.Writer(go_result) tmpl = textwrap.dedent("""\ package $package @@ -96,15 +94,28 @@ def main(args): writer.write_tmpl(tmpl, package=args.modname.split('.')[-1], script=util.go_str(args.script)) with writer.indent_block(2): - for s in sorted(mod_block.strings): + for s in sorted(module_block.strings): writer.write('ß{} := πg.InternStr({})'.format(s, util.go_str(s))) - writer.write_temp_decls(mod_block) - writer.write_block(mod_block, visitor.writer.getvalue()) + writer.write_temp_decls(module_block) + writer.write_block(module_block, visitor.writer.getvalue()) writer.write_tmpl(textwrap.dedent("""\ \t\treturn nil, πE \t}) \tπg.RegisterModule($modname, Code) }"""), modname=util.go_str(args.modname)) + + try: + if args.output: + go_output = open(args.output, 'w') + else: + go_output = sys.stdout + except IOError: + print >> sys.stderr, str(e) + return 2 + + go_result.seek(0) + go_output.write(go_result.read()) + go_output.close() return 0 From 8b5769d08c49e855c144411188aba3d16980988a Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Mon, 6 Nov 2017 19:30:00 -0200 Subject: [PATCH 04/24] [HACK] `make run` keeps the final code on the fs --- tools/grumprun | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/grumprun b/tools/grumprun index fd237713..00aadc0b 100755 --- a/tools/grumprun +++ b/tools/grumprun @@ -99,7 +99,7 @@ def main(args): f.write(module_tmpl.substitute(package=package, imports=imports)) return subprocess.Popen('go run ' + go_main, shell=True).wait() finally: - shutil.rmtree(workdir) + print 'shutil.rmtree(%s)' % workdir def _package_name(modname): From e60e07269cb667700d6b5f372fb1e9a8f2ece6ee Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Tue, 7 Nov 2017 18:52:38 -0200 Subject: [PATCH 05/24] [WIP] grumpc -astest to output as a _test.go file structure --- tools/grumpc | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tools/grumpc b/tools/grumpc index ad5cc8a3..fa71629a 100755 --- a/tools/grumpc +++ b/tools/grumpc @@ -36,6 +36,7 @@ parser = argparse.ArgumentParser() parser.add_argument('script', help='Python source filename') parser.add_argument('-modname', default='__main__', help='Python module name') parser.add_argument('-output', default=None, help='Golang output file path (defaults to stdout)') +parser.add_argument('-astest', default=False, action='store_true', help='Output as a test suite.') def main(args): @@ -86,12 +87,16 @@ def main(args): tmpl = textwrap.dedent("""\ package $package import πg "grumpy" + $import_testing var Code *πg.Code func init() { \tCode = πg.NewCode("", $script, nil, 0, func(πF *πg.Frame, _ []*πg.Object) (*πg.Object, *πg.BaseException) { \t\tvar πR *πg.Object; _ = πR \t\tvar πE *πg.BaseException; _ = πE""") - writer.write_tmpl(tmpl, package=args.modname.split('.')[-1], + + go_package_name = args.modname.split('.')[-1] + writer.write_tmpl(tmpl, package=go_package_name, + import_testing='import πt "testing"' if args.astest else '', script=util.go_str(args.script)) with writer.indent_block(2): for s in sorted(module_block.strings): @@ -104,6 +109,20 @@ def main(args): \tπg.RegisterModule($modname, Code) }"""), modname=util.go_str(args.modname)) + if args.astest: + + tmpl = textwrap.dedent("""\ + + func TestRunCode(t *testing.T) { + \tinit() + \tπg.ImportModule(grumpy.NewRootFrame(), "traceback") + \tπg.RunMain(Code) + } + """) + + writer.write_tmpl(tmpl, package='%s_test' % go_package_name) + writer.write_tmpl(tmpl,) + try: if args.output: go_output = open(args.output, 'w') From feece97ead79a7c297d091d733bbad640beb4775 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Thu, 9 Nov 2017 09:57:16 -0200 Subject: [PATCH 06/24] Provide $modname to test code, if needed --- tools/grumpc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/grumpc b/tools/grumpc index fa71629a..1ad26a11 100755 --- a/tools/grumpc +++ b/tools/grumpc @@ -95,6 +95,7 @@ def main(args): \t\tvar πE *πg.BaseException; _ = πE""") go_package_name = args.modname.split('.')[-1] + modname = util.go_str(args.modname) writer.write_tmpl(tmpl, package=go_package_name, import_testing='import πt "testing"' if args.astest else '', script=util.go_str(args.script)) @@ -107,7 +108,7 @@ def main(args): \t\treturn nil, πE \t}) \tπg.RegisterModule($modname, Code) - }"""), modname=util.go_str(args.modname)) + }"""), modname=modname) if args.astest: @@ -116,12 +117,12 @@ def main(args): func TestRunCode(t *testing.T) { \tinit() \tπg.ImportModule(grumpy.NewRootFrame(), "traceback") + \t//πg.ImportModule(grumpy.NewRootFrame(), $modname) \tπg.RunMain(Code) } """) - writer.write_tmpl(tmpl, package='%s_test' % go_package_name) - writer.write_tmpl(tmpl,) + writer.write_tmpl(tmpl, modname=modname) try: if args.output: From 02e0f690e6afe5f70e721995543c101403bbfe7d Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Mon, 11 Dec 2017 22:52:27 -0200 Subject: [PATCH 07/24] new tools/gentest, to generate module_test.go from .py files --- tools/genmake | 5 +++ tools/gentest | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100755 tools/gentest diff --git a/tools/genmake b/tools/genmake index 21d35018..c90d0cff 100755 --- a/tools/genmake +++ b/tools/genmake @@ -69,10 +69,15 @@ def main(args): modname = basename.replace(os.sep, '.') ar_name = os.path.join(pkg_dir, '__python__', basename + '.a') go_file = os.path.join(pydir, basename, 'module.go') + gotest_file = os.path.join(pydir, basename, 'module_test.go') _PrintRule(go_file, [os.path.join(dirpath, filename)], ['grumpc -modname={} $< > $@'.format(modname)], echo_debug=True) + _PrintRule(gotest_file, + [os.path.join(dirpath, filename)], + ['gentest -modname={} $< > $@'.format(modname)], + echo_debug=True) recipe = (r"""pydeps -modname=%s $< | awk '{gsub(/\./, "/", $$0); """ r"""print "%s: %s/__python__/" $$0 ".a"}' > $@""") diff --git a/tools/gentest b/tools/gentest new file mode 100755 index 00000000..98e6ecb7 --- /dev/null +++ b/tools/gentest @@ -0,0 +1,99 @@ +#!/usr/bin/env python + +# Copyright 2016 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""gentest creates a Golang module_test.go from a Python file, for coverage. + +Usage: $ gentest -m # Create test from the named module. +""" + +import argparse +import os +import sys +import textwrap + +from grumpy.compiler import imputil + +parser = argparse.ArgumentParser() +parser.add_argument('-m', '--modname', help='Run the named module') + + +template = textwrap.dedent(""" + package {modname} + import ( + "os" + "grumpy" + {imports} + ) + func TestRunCode(t *testing.T) { + grumpy.ImportModule(grumpy.NewRootFrame(), "traceback") + if grumpy.RunMain(Code) != 0 { + t.Fail() + } + } +""") + + +def _package_name(modname): + if modname.startswith('__go__/'): + return '__python__/' + modname + return '__python__/' + modname.replace('.', '/') + + +def _get_gopath(): + gopath = os.getenv('GOPATH', None) + if not gopath: + print >> sys.stderr, 'GOPATH not set' + raise RuntimeError('GOPATH not set') + return gopath + + +def main(args): + modname = args.modname + if not modname: + raise NotImplementedError("Should provide 'modname'") + + gopath = _get_gopath() + workdir = '.' # It is completely wrong for now. + py_dir = os.path.join(workdir, 'src', '__python__') + mod_dir = os.path.join(py_dir, modname) + # os.makedirs(mod_dir) + script = os.path.join(py_dir, 'module.py') + gopath = gopath + os.pathsep + workdir + package = _package_name(modname) + + names = imputil.calculate_transitive_deps(modname, script, gopath) + + # Find the script associated with the given module. + for d in gopath.split(os.pathsep): + script = imputil.find_script( + os.path.join(d, 'src', '__python__'), modname) + if script: + break + else: + raise RuntimeError("can't find module %s", modname) + + names = imputil.calculate_transitive_deps(modname, script, gopath) + # Make sure traceback is available in all Python binaries. + names.add('traceback') + + imports = '\n '.join(_package_name(name) for name in names) + + testfile_contents = template.format(modname=modname, imports=imports) + with open(os.open(os.path.join(mod_dir, 'module_test.go'), 'w')) as go_testfile: + go_testfile.write(testfile_contents) + + +if __name__ == '__main__': + sys.exit(main(parser.parse_args())) From 087f72073f81c50071cee98e1a8f7e0266847d86 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Mon, 11 Dec 2017 22:54:10 -0200 Subject: [PATCH 08/24] Use argparse to enforce "required modname" --- tools/gentest | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/gentest b/tools/gentest index 98e6ecb7..ebfd4772 100755 --- a/tools/gentest +++ b/tools/gentest @@ -26,7 +26,7 @@ import textwrap from grumpy.compiler import imputil parser = argparse.ArgumentParser() -parser.add_argument('-m', '--modname', help='Run the named module') +parser.add_argument('-m', '--modname', help='Module to generate a _test.go file to', required=True) template = textwrap.dedent(""" @@ -61,9 +61,6 @@ def _get_gopath(): def main(args): modname = args.modname - if not modname: - raise NotImplementedError("Should provide 'modname'") - gopath = _get_gopath() workdir = '.' # It is completely wrong for now. py_dir = os.path.join(workdir, 'src', '__python__') From 06f42ec01ad99520789c4c0caf5fe9b1c8f199dd Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Tue, 12 Dec 2017 19:17:14 -0200 Subject: [PATCH 09/24] Inform the makefile to generate the module_test.go files --- Makefile | 3 ++- tools/genmake | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9398f9e7..11233580 100644 --- a/Makefile +++ b/Makefile @@ -130,7 +130,7 @@ ACCEPT_PY_PASS_FILES := $(patsubst %,build/%_py.pass,$(filter-out %/native_test, BENCHMARKS := $(patsubst %.py,%,$(wildcard benchmarks/*.py)) BENCHMARK_BINS := $(patsubst %,build/%_benchmark,$(BENCHMARKS)) -TOOL_BINS = $(patsubst %,build/bin/%,benchcmp coverparse diffrange genmake pydeps) +TOOL_BINS = $(patsubst %,build/bin/%,benchcmp coverparse diffrange genmake gentest pydeps) GOLINT_BIN = build/bin/golint PYLINT_BIN = build/bin/pylint @@ -294,6 +294,7 @@ build/stdlib.mk: build/bin/genmake | $(STDLIB_SRCS) -include build/stdlib.mk $(patsubst %,build/src/__python__/%/module.go,$(STDLIB_PACKAGES)): $(COMPILER) +$(patsubst %,build/src/__python__/%/module_test.go,$(STDLIB_PACKAGES)): build/bin/gentest $(COMPILER) $(patsubst %,build/src/__python__/%/module.d,$(STDLIB_PACKAGES)): build/bin/pydeps $(PYTHONPARSER_SRCS) $(COMPILER) $(patsubst %,$(PKG_DIR)/__python__/%.a,$(STDLIB_PACKAGES)): $(RUNTIME) diff --git a/tools/genmake b/tools/genmake index c90d0cff..67ba79cb 100755 --- a/tools/genmake +++ b/tools/genmake @@ -86,7 +86,7 @@ def main(args): [recipe % (modname, ar_name, pkg_dir)]) go_package = '__python__/' + basename.replace(os.sep, '/') recipe = 'go tool compile -o $@ -p {} -complete -I {} -pack $<' - _PrintRule(ar_name, [go_file], [recipe.format(go_package, pkg_dir)]) + _PrintRule(ar_name, [go_file, gotest_file], [recipe.format(go_package, pkg_dir)]) if args.all_target: _PrintRule(args.all_target, [ar_name], []) print '-include {}\n'.format(dep_file) From c432a77d89e1696a5ff49e3101436a60cfda4e25 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Tue, 12 Dec 2017 19:22:36 -0200 Subject: [PATCH 10/24] Detecting and producing testfiles correctly --- tools/gentest | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/gentest b/tools/gentest index ebfd4772..37b8d24a 100755 --- a/tools/gentest +++ b/tools/gentest @@ -26,15 +26,15 @@ import textwrap from grumpy.compiler import imputil parser = argparse.ArgumentParser() -parser.add_argument('-m', '--modname', help='Module to generate a _test.go file to', required=True) +parser.add_argument('-modname', help='Module to generate a _test.go file to', required=True) template = textwrap.dedent(""" - package {modname} + package %s import ( "os" "grumpy" - {imports} + %s ) func TestRunCode(t *testing.T) { grumpy.ImportModule(grumpy.NewRootFrame(), "traceback") @@ -62,11 +62,11 @@ def _get_gopath(): def main(args): modname = args.modname gopath = _get_gopath() - workdir = '.' # It is completely wrong for now. + workdir = 'build' # It is ok _right now_ py_dir = os.path.join(workdir, 'src', '__python__') mod_dir = os.path.join(py_dir, modname) - # os.makedirs(mod_dir) - script = os.path.join(py_dir, 'module.py') + + script = os.path.join(py_dir, '%s.py' % modname) gopath = gopath + os.pathsep + workdir package = _package_name(modname) @@ -85,10 +85,10 @@ def main(args): # Make sure traceback is available in all Python binaries. names.add('traceback') - imports = '\n '.join(_package_name(name) for name in names) + imports = '\n '.join('"%s"' % _package_name(name) for name in names) - testfile_contents = template.format(modname=modname, imports=imports) - with open(os.open(os.path.join(mod_dir, 'module_test.go'), 'w')) as go_testfile: + testfile_contents = template % (modname, imports) + with open(os.path.join(mod_dir, 'module_test.go'), 'w') as go_testfile: go_testfile.write(testfile_contents) From 4a61060b4ac48f13b7b10299be673c3a79d67dab Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Tue, 12 Dec 2017 19:23:17 -0200 Subject: [PATCH 11/24] "softfail" if no .py file exists (or "softworks") --- tools/gentest | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/gentest b/tools/gentest index 37b8d24a..c1ac504c 100755 --- a/tools/gentest +++ b/tools/gentest @@ -70,6 +70,9 @@ def main(args): gopath = gopath + os.pathsep + workdir package = _package_name(modname) + if not os.path.isfile(script): + return # The script does not exist. And is OK! + names = imputil.calculate_transitive_deps(modname, script, gopath) # Find the script associated with the given module. From 63b87f7a1e43be776d47b793250bc8fa8f613a89 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Tue, 12 Dec 2017 19:45:10 -0200 Subject: [PATCH 12/24] Oops. --- tools/genmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/genmake b/tools/genmake index 67ba79cb..55ead03e 100755 --- a/tools/genmake +++ b/tools/genmake @@ -76,7 +76,7 @@ def main(args): echo_debug=True) _PrintRule(gotest_file, [os.path.join(dirpath, filename)], - ['gentest -modname={} $< > $@'.format(modname)], + ['gentest -modname={} > $@'.format(modname)], echo_debug=True) recipe = (r"""pydeps -modname=%s $< | awk '{gsub(/\./, "/", $$0); """ From 991a52ea83d408bcad1230b65563366f559972c6 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Wed, 13 Dec 2017 17:47:29 -0200 Subject: [PATCH 13/24] gentest: 4-spaces -> 2-spaces --- tools/gentest | 94 +++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/tools/gentest b/tools/gentest index c1ac504c..13f1b163 100755 --- a/tools/gentest +++ b/tools/gentest @@ -30,70 +30,70 @@ parser.add_argument('-modname', help='Module to generate a _test.go file to', re template = textwrap.dedent(""" - package %s - import ( - "os" - "grumpy" - %s - ) - func TestRunCode(t *testing.T) { - grumpy.ImportModule(grumpy.NewRootFrame(), "traceback") - if grumpy.RunMain(Code) != 0 { - t.Fail() - } - } + package %s + import ( + \t"os" + \t"grumpy" + \t%s + ) + func TestRunCode(t *testing.T) { + \tgrumpy.ImportModule(grumpy.NewRootFrame(), "traceback") + \tif grumpy.RunMain(Code) != 0 { + \t\tt.Fail() + \t} + } """) def _package_name(modname): - if modname.startswith('__go__/'): - return '__python__/' + modname - return '__python__/' + modname.replace('.', '/') + if modname.startswith('__go__/'): + return '__python__/' + modname + return '__python__/' + modname.replace('.', '/') def _get_gopath(): - gopath = os.getenv('GOPATH', None) - if not gopath: - print >> sys.stderr, 'GOPATH not set' - raise RuntimeError('GOPATH not set') - return gopath + gopath = os.getenv('GOPATH', None) + if not gopath: + print >> sys.stderr, 'GOPATH not set' + raise RuntimeError('GOPATH not set') + return gopath def main(args): - modname = args.modname - gopath = _get_gopath() - workdir = 'build' # It is ok _right now_ - py_dir = os.path.join(workdir, 'src', '__python__') - mod_dir = os.path.join(py_dir, modname) + modname = args.modname + gopath = _get_gopath() + workdir = 'build' # It is ok _right now_ + py_dir = os.path.join(workdir, 'src', '__python__') + mod_dir = os.path.join(py_dir, modname) - script = os.path.join(py_dir, '%s.py' % modname) - gopath = gopath + os.pathsep + workdir - package = _package_name(modname) + script = os.path.join(py_dir, '%s.py' % modname) + gopath = gopath + os.pathsep + workdir + package = _package_name(modname) - if not os.path.isfile(script): - return # The script does not exist. And is OK! + if not os.path.isfile(script): + return # The script does not exist. And is OK! - names = imputil.calculate_transitive_deps(modname, script, gopath) + names = imputil.calculate_transitive_deps(modname, script, gopath) - # Find the script associated with the given module. - for d in gopath.split(os.pathsep): - script = imputil.find_script( - os.path.join(d, 'src', '__python__'), modname) - if script: - break - else: - raise RuntimeError("can't find module %s", modname) + # Find the script associated with the given module. + for d in gopath.split(os.pathsep): + script = imputil.find_script( + os.path.join(d, 'src', '__python__'), modname) + if script: + break + else: + raise RuntimeError("can't find module %s", modname) - names = imputil.calculate_transitive_deps(modname, script, gopath) - # Make sure traceback is available in all Python binaries. - names.add('traceback') + names = imputil.calculate_transitive_deps(modname, script, gopath) + # Make sure traceback is available in all Python binaries. + names.add('traceback') - imports = '\n '.join('"%s"' % _package_name(name) for name in names) + imports = '\n\t'.join('"%s"' % _package_name(name) for name in names) - testfile_contents = template % (modname, imports) - with open(os.path.join(mod_dir, 'module_test.go'), 'w') as go_testfile: - go_testfile.write(testfile_contents) + testfile_contents = template % (modname, imports) + with open(os.path.join(mod_dir, 'module_test.go'), 'w') as go_testfile: + go_testfile.write(testfile_contents) if __name__ == '__main__': - sys.exit(main(parser.parse_args())) + sys.exit(main(parser.parse_args())) From e9b8bcf7ea7e3bb1976c6de1b6b11414f4d70a50 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Wed, 13 Dec 2017 17:57:51 -0200 Subject: [PATCH 14/24] Make pylint happy --- tools/genmake | 3 ++- tools/gentest | 7 +++---- tools/grumpc | 6 ++++-- tools/grumprun | 1 - 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tools/genmake b/tools/genmake index 55ead03e..30de6ee1 100755 --- a/tools/genmake +++ b/tools/genmake @@ -86,7 +86,8 @@ def main(args): [recipe % (modname, ar_name, pkg_dir)]) go_package = '__python__/' + basename.replace(os.sep, '/') recipe = 'go tool compile -o $@ -p {} -complete -I {} -pack $<' - _PrintRule(ar_name, [go_file, gotest_file], [recipe.format(go_package, pkg_dir)]) + _PrintRule(ar_name, [go_file, gotest_file], + [recipe.format(go_package, pkg_dir)]) if args.all_target: _PrintRule(args.all_target, [ar_name], []) print '-include {}\n'.format(dep_file) diff --git a/tools/gentest b/tools/gentest index 13f1b163..a7fcd22a 100755 --- a/tools/gentest +++ b/tools/gentest @@ -26,7 +26,8 @@ import textwrap from grumpy.compiler import imputil parser = argparse.ArgumentParser() -parser.add_argument('-modname', help='Module to generate a _test.go file to', required=True) +parser.add_argument('-modname', required=True, + help='Module to generate a _test.go file to') template = textwrap.dedent(""" @@ -68,7 +69,6 @@ def main(args): script = os.path.join(py_dir, '%s.py' % modname) gopath = gopath + os.pathsep + workdir - package = _package_name(modname) if not os.path.isfile(script): return # The script does not exist. And is OK! @@ -77,8 +77,7 @@ def main(args): # Find the script associated with the given module. for d in gopath.split(os.pathsep): - script = imputil.find_script( - os.path.join(d, 'src', '__python__'), modname) + script = imputil.find_script(os.path.join(d, 'src', '__python__'), modname) if script: break else: diff --git a/tools/grumpc b/tools/grumpc index 1ad26a11..3cb09fed 100755 --- a/tools/grumpc +++ b/tools/grumpc @@ -35,8 +35,10 @@ from grumpy import pythonparser parser = argparse.ArgumentParser() parser.add_argument('script', help='Python source filename') parser.add_argument('-modname', default='__main__', help='Python module name') -parser.add_argument('-output', default=None, help='Golang output file path (defaults to stdout)') -parser.add_argument('-astest', default=False, action='store_true', help='Output as a test suite.') +parser.add_argument('-output', default=None, + help='Golang output file path (defaults to stdout)') +parser.add_argument('-astest', default=False, action='store_true', + help='Output as a test suite.') def main(args): diff --git a/tools/grumprun b/tools/grumprun index 00aadc0b..a5e420b5 100755 --- a/tools/grumprun +++ b/tools/grumprun @@ -23,7 +23,6 @@ Usage: $ grumprun -m # Run the named module. import argparse import os import random -import shutil import string import subprocess import sys From b7a81f25c3de06203d956e5c8694a3fbd83dc696 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Thu, 14 Dec 2017 12:08:41 -0200 Subject: [PATCH 15/24] Make test output happy --- tools/grumprun | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/grumprun b/tools/grumprun index a5e420b5..0b2baa1f 100755 --- a/tools/grumprun +++ b/tools/grumprun @@ -98,7 +98,8 @@ def main(args): f.write(module_tmpl.substitute(package=package, imports=imports)) return subprocess.Popen('go run ' + go_main, shell=True).wait() finally: - print 'shutil.rmtree(%s)' % workdir + # print 'shutil.rmtree(%s)' % workdir + pass def _package_name(modname): From 99e8f9a37225a41235c56919402c0f973b8f956c Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Thu, 14 Dec 2017 12:10:17 -0200 Subject: [PATCH 16/24] Redirect msgs to stderr --- tools/grumprun | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/grumprun b/tools/grumprun index 0b2baa1f..8ebb2d54 100755 --- a/tools/grumprun +++ b/tools/grumprun @@ -98,8 +98,7 @@ def main(args): f.write(module_tmpl.substitute(package=package, imports=imports)) return subprocess.Popen('go run ' + go_main, shell=True).wait() finally: - # print 'shutil.rmtree(%s)' % workdir - pass + print >> os.stderr, 'shutil.rmtree(%s)' % workdir def _package_name(modname): From 84f3a0d8f519c8350b8f75bd9d6d943455682e73 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Thu, 14 Dec 2017 12:26:35 -0200 Subject: [PATCH 17/24] Oops. --- tools/grumprun | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/grumprun b/tools/grumprun index 8ebb2d54..0e725be5 100755 --- a/tools/grumprun +++ b/tools/grumprun @@ -98,7 +98,7 @@ def main(args): f.write(module_tmpl.substitute(package=package, imports=imports)) return subprocess.Popen('go run ' + go_main, shell=True).wait() finally: - print >> os.stderr, 'shutil.rmtree(%s)' % workdir + print >> os.sys.stderr, 'shutil.rmtree(%s)' % workdir def _package_name(modname): From 2b0a12e3b2f10c0402a4a6d14b281d77dfdeec44 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Thu, 14 Dec 2017 14:54:05 -0200 Subject: [PATCH 18/24] Is it? --- tools/grumprun | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/grumprun b/tools/grumprun index 0e725be5..fd237713 100755 --- a/tools/grumprun +++ b/tools/grumprun @@ -23,6 +23,7 @@ Usage: $ grumprun -m # Run the named module. import argparse import os import random +import shutil import string import subprocess import sys @@ -98,7 +99,7 @@ def main(args): f.write(module_tmpl.substitute(package=package, imports=imports)) return subprocess.Popen('go run ' + go_main, shell=True).wait() finally: - print >> os.sys.stderr, 'shutil.rmtree(%s)' % workdir + shutil.rmtree(workdir) def _package_name(modname): From bbf6cb4acf8696c177601bd940bc41e76bd177a9 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Fri, 15 Dec 2017 00:31:23 -0200 Subject: [PATCH 19/24] Silence "unused" errors for transitive imports --- tools/gentest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gentest b/tools/gentest index a7fcd22a..1a6d134c 100755 --- a/tools/gentest +++ b/tools/gentest @@ -33,7 +33,7 @@ parser.add_argument('-modname', required=True, template = textwrap.dedent(""" package %s import ( - \t"os" + \t"testing" \t"grumpy" \t%s ) @@ -87,7 +87,7 @@ def main(args): # Make sure traceback is available in all Python binaries. names.add('traceback') - imports = '\n\t'.join('"%s"' % _package_name(name) for name in names) + imports = '\n\t'.join('_ "%s"' % _package_name(name) for name in names) testfile_contents = template % (modname, imports) with open(os.path.join(mod_dir, 'module_test.go'), 'w') as go_testfile: From 9dc9d037e240521a20d884c8c9092a35ec6ec80d Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Fri, 15 Dec 2017 00:49:21 -0200 Subject: [PATCH 20/24] Generate _test.go only for _test.py files --- tools/genmake | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/genmake b/tools/genmake index 30de6ee1..06c396e9 100755 --- a/tools/genmake +++ b/tools/genmake @@ -70,14 +70,17 @@ def main(args): ar_name = os.path.join(pkg_dir, '__python__', basename + '.a') go_file = os.path.join(pydir, basename, 'module.go') gotest_file = os.path.join(pydir, basename, 'module_test.go') + ar_deps = [go_file] _PrintRule(go_file, [os.path.join(dirpath, filename)], ['grumpc -modname={} $< > $@'.format(modname)], echo_debug=True) - _PrintRule(gotest_file, - [os.path.join(dirpath, filename)], - ['gentest -modname={} > $@'.format(modname)], - echo_debug=True) + if modname.endswith(('_test', '_tests')): + ar_deps.append(gotest_file) + _PrintRule(gotest_file, + [os.path.join(dirpath, filename)], + ['gentest -modname={} > $@'.format(modname)], + echo_debug=True) recipe = (r"""pydeps -modname=%s $< | awk '{gsub(/\./, "/", $$0); """ r"""print "%s: %s/__python__/" $$0 ".a"}' > $@""") @@ -86,8 +89,7 @@ def main(args): [recipe % (modname, ar_name, pkg_dir)]) go_package = '__python__/' + basename.replace(os.sep, '/') recipe = 'go tool compile -o $@ -p {} -complete -I {} -pack $<' - _PrintRule(ar_name, [go_file, gotest_file], - [recipe.format(go_package, pkg_dir)]) + _PrintRule(ar_name, ar_deps, [recipe.format(go_package, pkg_dir)]) if args.all_target: _PrintRule(args.all_target, [ar_name], []) print '-include {}\n'.format(dep_file) From 764af4ceb893ffe6097e3c1928b89c45eb333c7b Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Thu, 21 Dec 2017 16:02:25 -0200 Subject: [PATCH 21/24] time_test.py generates 'package time' --- tools/gentest | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gentest b/tools/gentest index 1a6d134c..09ed852d 100755 --- a/tools/gentest +++ b/tools/gentest @@ -89,7 +89,8 @@ def main(args): imports = '\n\t'.join('_ "%s"' % _package_name(name) for name in names) - testfile_contents = template % (modname, imports) + testfile_modname = modname[:-5] if modname.endswith('_test') else modname + testfile_contents = template % (testfile_modname, imports) with open(os.path.join(mod_dir, 'module_test.go'), 'w') as go_testfile: go_testfile.write(testfile_contents) From 8d321f027cd3f1278c032577b2ae2295e7c292e8 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Thu, 21 Dec 2017 16:15:42 -0200 Subject: [PATCH 22/24] [HACK] Should suppress _test from package name --- tools/grumpc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/grumpc b/tools/grumpc index 3cb09fed..d3ddb9fa 100755 --- a/tools/grumpc +++ b/tools/grumpc @@ -97,8 +97,16 @@ def main(args): \t\tvar πE *πg.BaseException; _ = πE""") go_package_name = args.modname.split('.')[-1] + + # HACK: Should suppress _test from package name + # See: https://github.com/google/grumpy/issues/383#issuecomment-353394740 + if go_package_name.endswith('_test'): + final_package_name = go_package_name[:-5] + else: + final_package_name = go_package_name + modname = util.go_str(args.modname) - writer.write_tmpl(tmpl, package=go_package_name, + writer.write_tmpl(tmpl, package=final_package_name, import_testing='import πt "testing"' if args.astest else '', script=util.go_str(args.script)) with writer.indent_block(2): From e10a4ce4e210ee1bbb28dd4ba93ac7b21d2a00fe Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Thu, 21 Dec 2017 17:20:07 -0200 Subject: [PATCH 23/24] Handle submodules on modname --- tools/gentest | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gentest b/tools/gentest index 09ed852d..bd5a49eb 100755 --- a/tools/gentest +++ b/tools/gentest @@ -65,10 +65,11 @@ def main(args): gopath = _get_gopath() workdir = 'build' # It is ok _right now_ py_dir = os.path.join(workdir, 'src', '__python__') - mod_dir = os.path.join(py_dir, modname) + mod_dir = os.path.join(py_dir, modname.replace('.', '/')) - script = os.path.join(py_dir, '%s.py' % modname) + script = os.path.join(py_dir, '%s.py' % modname.replace('.', '/')) gopath = gopath + os.pathsep + workdir + testfile_modname = modname[:-5] if modname.endswith('_test') else modname if not os.path.isfile(script): return # The script does not exist. And is OK! @@ -89,7 +90,6 @@ def main(args): imports = '\n\t'.join('_ "%s"' % _package_name(name) for name in names) - testfile_modname = modname[:-5] if modname.endswith('_test') else modname testfile_contents = template % (testfile_modname, imports) with open(os.path.join(mod_dir, 'module_test.go'), 'w') as go_testfile: go_testfile.write(testfile_contents) From dd2436786761a73f8da3c12c8b3c46a83adff185 Mon Sep 17 00:00:00 2001 From: Alan Justino Date: Thu, 21 Dec 2017 18:20:27 -0200 Subject: [PATCH 24/24] test_modname is only the last package part --- tools/gentest | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gentest b/tools/gentest index bd5a49eb..ae957270 100755 --- a/tools/gentest +++ b/tools/gentest @@ -70,6 +70,7 @@ def main(args): script = os.path.join(py_dir, '%s.py' % modname.replace('.', '/')) gopath = gopath + os.pathsep + workdir testfile_modname = modname[:-5] if modname.endswith('_test') else modname + testfile_modname = testfile_modname.split('.')[-1] if not os.path.isfile(script): return # The script does not exist. And is OK!