From 534743f196d19d85425679e87e9e54230311c44e Mon Sep 17 00:00:00 2001 From: Bruce Eckel Date: Sat, 6 Jun 2015 15:07:33 -0700 Subject: [PATCH] tools --- tools/AttachResults.py | 284 ++++++++++++++++++++++++++--------------- tools/Examples.py | 12 +- tools/Validate.py | 31 ++++- 3 files changed, 221 insertions(+), 106 deletions(-) diff --git a/tools/AttachResults.py b/tools/AttachResults.py index 210008b8..66ac519d 100644 --- a/tools/AttachResults.py +++ b/tools/AttachResults.py @@ -3,18 +3,17 @@ Append output and error files to Java files """ TODO = """ -- Add: -} /* Output: (None) *///:~ -To files that produce no output. + +- Display all files with less than 100% match (rather than putting percentage and "Sample" in) + Rely on visual inspection of non-matching file? + Have a list of files to exclude normally, and inspect ocasionally + - Test to make sure that None files indeed have no output - Ambitious: Allow edits of "AttachedResults.txt" which are then pulled back into the source files. -- 1st and last 10 lines, with ... in between? {OutputFirstAndLast: 10 Lines} - - } /* Same output as RoShamBo2.java *///:~ } /* Output: (Same as RoShamBo2.java) *///:~ @@ -28,85 +27,108 @@ from betools import CmdLine, visitDir, ruler, head maxlinewidth = 59 examplePath = Path(r"C:\Users\Bruce\Dropbox\__TIJ4-ebook\ExtractedExamples") -maindef = re.compile("public\s+static\s+void\s+main") -class JFile: + +class JavaMain: + + maindef = re.compile("public\s+static\s+void\s+main") + ellipses = ["[...]".center(maxlinewidth, '_')] + + class JFile: + """Could just manipulate this, then write it at the end""" + @staticmethod + def with_main(javaFilePath): + with javaFilePath.open() as doc: + code = doc.read() + if JavaMain.maindef.search(code): + return JavaMain.JFile(javaFilePath, code) + return None + def __init__(self, javaFilePath, code): + self.javaFilePath = javaFilePath + self.code = code + self.lines = self.code.splitlines() + self.output_line = None + for line in self.lines: + if "} /* Output:" in line: + self.output_line = line + self.newcode = "" @staticmethod - def with_main(javaFilePath): - with javaFilePath.open() as doc: - code = doc.read() - if maindef.search(code): - return JFile(code) + def create(javaFilePath): + j_file = JavaMain.JFile.with_main(javaFilePath) + if j_file is None: + return None + if "{ValidateByHand}" in j_file.code: + return None + if "/* Output: (None) */" in j_file.code: + return None + outfile = javaFilePath.with_name(javaFilePath.stem + "-output.txt") + errfile = javaFilePath.with_name(javaFilePath.stem + "-erroroutput.txt") + if outfile.exists() or errfile.exists(): + return JavaMain(javaFilePath, j_file, outfile, errfile) return None - def __init__(self, code): - self.code = code - self.lines = self.code.splitlines() + def __init__(self, javaFilePath, j_file, outfile, errfile): + self.javaFilePath = javaFilePath + self.j_file = j_file + self.outfile = outfile + self.errfile = errfile + self.first_and_last = None + self.first_lines = None - def has_output(self): - return "} /* Output:" in self.code + ol = self.j_file.output_line + if ol: + if "(First and last" in ol: + self.first_and_last = int(ol.partition("(First and last")[2].split()[0]) + elif "(First" in ol: + self.first_lines = int(ol.partition("(First")[2].split()[0]) - def output_line(self): - for line in self.lines: - if "} /* Output:" in line: - return line + result ="" + if outfile.exists(): + with outfile.open() as f: + out = f.read().strip() + if out: + if self.first_and_last: + lines = out.splitlines() + out = "\n".join(lines[:self.first_and_last] + JavaMain.ellipses + lines[-self.first_and_last:]) + elif self.first_lines: + lines = out.splitlines() + out = "\n".join(lines[:self.first_lines] + JavaMain.ellipses) + result += out + "\n" + if errfile.exists(): # Always include all of errfile + with errfile.open() as f: + err = f.read().strip() + if err: + result += "___[ Error Output ]___\n" + result += err + self.result = JavaMain.wrapOutput(result) + "\n" + + for line in self.j_file.lines: + if line.startswith("} ///:~"): + self.j_file.newcode += "} /* Output:\n" + self.j_file.newcode += self.result + "*///:~\n" + break + if line.startswith("} /* Output:"): + line = line.partition("*///:~")[0] + self.j_file.newcode += line + "\n" + self.j_file.newcode += self.result + "*///:~\n" + break + else: + self.j_file.newcode += line + "\n" + + def new_code(self): + return self.j_file.newcode + + @staticmethod + def wrapOutput(output): + lines = output.splitlines() + result = [] + for line in lines: + result += textwrap.wrap(line.rstrip(), width=maxlinewidth) + return "\n".join(result) -def wrapOutput(output): - lines = output.splitlines() - result = [] - for line in lines: - result += textwrap.wrap(line.rstrip(), width=maxlinewidth) - return "\n".join(result) - -def newOutput(javaFilePath): - outfile = javaFilePath.with_name(javaFilePath.stem + "-output.txt") - errfile = javaFilePath.with_name(javaFilePath.stem + "-erroroutput.txt") - result ="" - if outfile.exists(): - with outfile.open() as f: - out = f.read().strip() - if out: - result += out + "\n" - if errfile.exists(): - with errfile.open() as f: - err = f.read().strip() - if err: - result += "--[ Error Output ]--\n" - result += err - result = wrapOutput(result) - if result: - return result + "\n" - return None - - -def appendOutputFiles(javaFilePath): - jfile = JFile.with_main(javaFilePath) - if jfile is None: - return - output = newOutput(javaFilePath) - if not output: - return - if not self.output_tags.has_output: # no /* Output: at all - with self.javaFilePath.open() as jf: - code = jf.read() - lines = code.splitlines() - while lines[-1].strip() is "": - lines.pop() - assert lines[-1].rstrip() == "} ///:~" - lines[-1] = "} /* Output:" - lines.append(self.new_output) - lines.append("*///:~") - result = "\n".join(lines) + "\n" - with self.javaFilePath.open("w") as jf: - jf.write(result) - return result - else: - print("{} already has Output!".format(self.javaFilePath)) - sys.exit() - @CmdLine('o') def allOutputTagLines(): """Shows all lines starting with } /*""" @@ -126,64 +148,126 @@ def outputTagTypes(): types = set() os.chdir(str(examplePath)) for jfp in Path(".").rglob("*.java"): - jf = JFile.with_main(jfp) + jf = JavaMain.JFile.with_main(jfp) if jf is None: continue - if jf.has_output(): - types.add(jf.output_line()) + if jf.output_line: + types.add(jf.output_line) pprint.pprint(types) + @CmdLine('e') def extractResults(): """Test extraction of all results""" os.chdir(str(examplePath)) with Path("AttachedResults.txt").open('w') as results: for jfp in Path(".").rglob("*.java"): - output = newOutput(jfp) - if output: + j_main = JavaMain.create(jfp) + if j_main: results.write(ruler(jfp)) - jf = JFile.with_main(jfp) - if jf is None: - continue - outline = jf.output_line() + outline = j_main.j_file.output_line if outline: results.write(outline + "\n") - results.write(output) - else: - results.write("[ No output for {} ]\n".format(jfp)) + results.write(j_main.result) + # else: + # results.write("[ No output for {} ]\n".format(jfp)) + os.system("subl AttachedResults.txt") @CmdLine('n') def noOutputFixup(): - """Attach no output lines to empty output files""" - # Exclude gui and swt directories! + """Attach "Output: (None)" lines to empty output files""" os.chdir(str(examplePath)) - test = open("test.txt", 'w') + # test = open("test.txt", 'w') for jfp in Path(".").rglob("*.java"): - jf = JFile.with_main(jfp) + if "gui" in jfp.parts or "swt" in jfp.parts: + continue + jf = JavaMain.JFile.with_main(jfp) if jf is None: continue - if not jf.has_output(): + if "{ValidateByHand}" in jf.code: + continue + if not jf.output_line: + if JavaMain.create(jfp): + continue newcode = "" for line in jf.lines: if line.startswith("} ///:~"): newcode += "} /* Output: (None) *///:~\n" else: newcode += line + "\n" - test.write(ruler(jfp)) - test.write(newcode) + with jfp.open('w') as f: + f.write(newcode) + os.system("subl {}".format(jfp)) + # test.write(ruler(jfp)) + # test.write(newcode) @CmdLine('a') def attachFiles(): """Attach standard and error output to all files""" os.chdir(str(examplePath)) + test = open("test.txt", 'w') for jfp in Path(".").rglob("*.java"): - jf = JFile.with_main(jfp) - if jf is None: + if "gui" in jfp.parts or "swt" in jfp.parts: continue - if jf.has_output(): - head(jfp) - print("\t{}".format(jf.output_line())) - + j_main = JavaMain.create(jfp) + if j_main is None: + continue + test.write(ruler()) + test.write(j_main.new_code()) + os.system("subl test.txt") if __name__ == '__main__': CmdLine.run() + + + +# def newOutput(javaFilePath): +# outfile = javaFilePath.with_name(javaFilePath.stem + "-output.txt") +# errfile = javaFilePath.with_name(javaFilePath.stem + "-erroroutput.txt") +# result ="" +# if outfile.exists(): +# with outfile.open() as f: +# out = f.read().strip() +# if out: +# result += out + "\n" +# if errfile.exists(): +# with errfile.open() as f: +# err = f.read().strip() +# if err: +# result += "___[ Error Output ]___\n" +# result += err +# result = wrapOutput(result) +# if result: +# return result + "\n" +# return None + + + + + + + +# def appendOutputFiles(javaFilePath): +# jfile = JFile.with_main(javaFilePath) +# if jfile is None: +# return +# output = newOutput(javaFilePath) +# if not output: +# return +# if not self.output_tags.has_output: # no /* Output: at all +# with self.javaFilePath.open() as jf: +# code = jf.read() +# lines = code.splitlines() +# while lines[-1].strip() is "": +# lines.pop() +# assert lines[-1].rstrip() == "} ///:~" +# lines[-1] = "} /* Output:" +# lines.append(self.new_output) +# lines.append("*///:~") +# result = "\n".join(lines) + "\n" +# with self.javaFilePath.open("w") as jf: +# jf.write(result) +# return result +# else: +# print("{} already has Output!".format(self.javaFilePath)) +# sys.exit() \ No newline at end of file diff --git a/tools/Examples.py b/tools/Examples.py index a142f836..ea0e483f 100644 --- a/tools/Examples.py +++ b/tools/Examples.py @@ -3,6 +3,9 @@ Extract code examples from TIJ Director's Cut plain text file. Creates Ant build.xml file for each subdirectory. """ +TODO = """ +incorporate exec_command into build.xml +""" from pathlib import Path import sys, os import re @@ -187,7 +190,6 @@ class CodeFileOptions(object): self.continue_on_error = True self.msg = "* Exception was Expected *" - self.alternatemainclass = None if "{main: " in self.codeFile.code: for line in self.codeFile.lines: @@ -195,6 +197,14 @@ class CodeFileOptions(object): self.alternatemainclass = line.split("{main:")[1].strip() self.alternatemainclass = self.alternatemainclass.rsplit("}", 1)[0] + self.exec_command = None + if "{Exec:" in self.codeFile.code: + for line in self.codeFile.lines: + if "{Exec:" in line: + self.exec_command = line.split("{Exec:")[1].strip() + self.exec_command = self.exec_command.rsplit("}", 1)[0] + self.exec_command = self.exec_command.strip() + self.timeout = None if "{TimeOut:" in self.codeFile.code: for line in self.codeFile.lines: diff --git a/tools/Validate.py b/tools/Validate.py index 799fecca..fc9336b9 100644 --- a/tools/Validate.py +++ b/tools/Validate.py @@ -28,6 +28,7 @@ maindef = re.compile("public\s+static\s+void\s+main") ############################################################################### # Powershell: https://gist.github.com/diyan/2850866 # http://marxsoftware.blogspot.com/2008/02/windows-powershell-and-java.html +allflags = dict() class Flags: discard = ["{Requires:"] @@ -48,8 +49,11 @@ class Flags: fl = fl.strip() arg = arg.strip() self.flags[fl] = arg + allflags[fl] = arg else: self.flags[flag] = None # Make an entry, but no arg + allflags[flag] = None + # allflags.add(flag) def __contains__(self, elt): return elt in self.flags @@ -125,7 +129,7 @@ class RunFiles: for java in RunFiles.base.rglob("*.java"): with java.open() as code: body = code.read() - if maindef.search(body): + if maindef.search(body) or "{Exec:" in body: self.runFiles.append(RunnableFile(java, body)) allMains = set(self.runFiles) self.runFiles = [f for f in self.runFiles if not [nr for nr in self.not_runnable if nr in f]] @@ -180,10 +184,25 @@ def createPowershellScript(): -RedirectStandardOutput {}-output.txt -RedirectStandardError {}-erroroutput.txt """.format(argquote, rf.javaArguments(), argquote, rf.name, rf.name) + + if "Exec" in rf: + print("Exec found in {}".format(rf.name)) + pprint.pprint(rf.flags.flags) + command = rf.flags.flags["Exec"].split() + pprint.pprint(command) + pstext = """\ + Start-Process + -FilePath "{}" + -ArgumentList {}{}{} + -NoNewWindow + -RedirectStandardOutput {}-output.txt + -RedirectStandardError {}-erroroutput.txt + """.format(command[0] ,argquote, " ".join(command[1:]), argquote, rf.name, rf.name) + pstext = textwrap.dedent(pstext).replace('\n', ' ') if "ThrowsException" in rf: pstext += " -Wait\n" - pstext += "Add-Content {}-erroroutput.txt '---[ Exception is Expected ]---'".format(rf.name) + pstext += "Add-Content {}-erroroutput.txt '___[ Exception is Expected ]___'".format(rf.name) ps.write("cd {}\n".format(os.getcwd())) ps.write(pstext + "\n") ps.write('Write-Host [{}] {}\n'.format(rf.relative, rf.name)) @@ -276,7 +295,7 @@ class Result: with self.errFilePath.open() as f: err = f.read().strip() if err: - result += "--[ Error Output ]--\n" + result += "___[ Error Output ]___\n" result += err return textwrap.wrap(result, width=maxlinewidth) @@ -386,7 +405,7 @@ def showProblemErrors(): continue if "LoggingException" in err: continue - if "---[ Exception is Expected ]---" in err: + if "___[ Exception is Expected ]___" in err: continue print(err) @@ -503,4 +522,6 @@ def clean_files(): w.write(code) -if __name__ == '__main__': CmdLine.run() +if __name__ == '__main__': + CmdLine.run() + pprint.pprint(allflags)