diff --git a/tools/Examples.py b/tools/Examples.py index 067ed5d4..c50f76da 100644 --- a/tools/Examples.py +++ b/tools/Examples.py @@ -159,7 +159,7 @@ class CodeFileOptions(object): self.cmdargs = line.split("{Args:")[1].strip() self.cmdargs = self.cmdargs.rsplit("}", 1)[0] - self.runbyhand = "{RunByHand}" in self.codeFile.code + self.validatebyhand = "{ValidateByHand}" in self.codeFile.code self.exclude = None if "{CompileTimeError}" in self.codeFile.code: @@ -208,7 +208,10 @@ class CodeFileOptions(object): def arguments(self): if self.cmdargs: - return """arguments="%s" """ % self.cmdargs + if '"' in self.cmdargs: + return """arguments='%s' """ % self.cmdargs + else: + return """arguments="%s" """ % self.cmdargs return "" def failOnError(self): @@ -306,7 +309,7 @@ class Chapter: def makeBuildFile(self): buildFile = startBuild % (self.dir.name, " ".join(self.excludes)) for cf in self.code_files: - if any([cf.name + ".java" in f for f in self.excludes]) or cf.options.runbyhand: + if any([cf.name + ".java" in f for f in self.excludes]) or cf.options.validatebyhand: continue buildFile += cf.run_command() buildFile += endBuild @@ -349,6 +352,7 @@ def extractAndCreateBuildFiles(): with open("run.bat", 'w') as run: run.write(r"python ..\Validate.py -p" + "\n") run.write(r"powershell .\runall.ps1" + "\n") + run.write(r"python ..\Validate.py -e" + "\n") @CmdLine('g') def generateAntClean(): diff --git a/tools/Validate.py b/tools/Validate.py index 2b59197a..04d8f12e 100644 --- a/tools/Validate.py +++ b/tools/Validate.py @@ -14,6 +14,8 @@ import difflib from collections import defaultdict from betools import CmdLine, visitDir, ruler, head +examplePath = Path(r"C:\Users\Bruce\Dropbox\__TIJ4-ebook\ExtractedExamples") + maindef = re.compile("public\s+static\s+void\s+main") ############################################################################### @@ -35,7 +37,7 @@ class Flags: self.flaglines = [line for line in self.flaglines if not [d for d in Flags.discard if d in line]] self.flags = dict() for flag in self.flaglines: - flag = flag[flag.index("{") + 1 : flag.index("}")].strip() + flag = flag[flag.index("{") + 1 : flag.rfind("}")].strip() if ":" in flag: fl, arg = flag.split(":") fl = fl.strip() @@ -60,7 +62,7 @@ class Flags: return str(self.flags.values()) def jvm_args(self): - return self.flags["JVMArgs"] if "JVMArgs" in self.flags else "" + return self.flags["JVMArgs"] + " " if "JVMArgs" in self.flags else "" def cmd_args(self): return " " + self.flags["Args"] if "Args" in self.flags else "" @@ -82,6 +84,9 @@ class RunnableFile: self._package = line.split("package ")[1].strip()[:-1] if self._package.replace('.', '/') not in self.lines[0]: self._package = "" + self.main = self.name + if "main" in self.flags: + self.main = self.flags.flags["main"] def __contains__(self, elt): return elt in self.flags @@ -97,7 +102,7 @@ class RunnableFile: return self.path.parent def javaArguments(self): - return self.flags.jvm_args() + self.package() + self.name + self.flags.cmd_args() + return self.flags.jvm_args() + self.package() + self.main + self.flags.cmd_args() def runCommand(self): return "java " + self.javaArguments() @@ -106,7 +111,7 @@ class RunnableFile: class RunFiles: # RunFirst is temporary? - not_runnable = ["RunByHand", "TimeOutDuringTesting", "CompileTimeError", 'TimeOut', 'RunFirst'] + not_runnable = ["ValidateByHand", "TimeOutDuringTesting", "CompileTimeError", 'TimeOut', 'RunFirst'] skip_dirs = ["gui", "swt"] base = Path(".") @@ -152,22 +157,28 @@ def createPowershellScript(): """ Create Powershell Script to run all programs and capture the output """ - assert Path.cwd().stem is "ExtractedExamples" + os.chdir(str(examplePath)) runFiles = RunFiles() startDir = os.getcwd() with open("runall.ps1", 'w') as ps: ps.write('''Start-Process -FilePath "ant" -ArgumentList "build" -NoNewWindow -Wait \n\n''') for rf in runFiles: with visitDir(rf.rundir()): + argquote = '"' + if '"' in rf.javaArguments() or '$' in rf.javaArguments(): + argquote = "'" pstext = """\ Start-Process -FilePath "java.exe" - -ArgumentList "{}" + -ArgumentList {}{}{} -NoNewWindow -RedirectStandardOutput {}-output.txt -RedirectStandardError {}-erroroutput.txt - """.format(rf.javaArguments(), rf.name, rf.name) + """.format(argquote, rf.javaArguments(), 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) ps.write("cd {}\n".format(os.getcwd())) ps.write(pstext + "\n") ps.write('Write-Host [{}] {}\n'.format(rf.relative, rf.name)) @@ -343,16 +354,34 @@ def fillInUnexcludedOutput(): @CmdLine("e") def findExceptionsFromRun(): """ - Find all the exceptions produced by runall.ps1 + Put the exceptions produced by runall.ps1 into errors.txt """ errors = [r for r in [Result.create(jfp) for jfp in RunFiles.base.rglob("*.java")] if r and r.errFilePath.stat().st_size] assert len(errors), "Must run runall.ps1 first" - for e in errors: - with e.errFilePath.open() as errfile: - head(e.errFilePath, "#") - print(errfile.read()) - head() + with (examplePath / "errors.txt").open('w') as errors_txt: + for e in errors: + with e.errFilePath.open() as errfile: + errors_txt.write("\n" + ruler(e.errFilePath, width=80)) + errors_txt.write(errfile.read()) + errors_txt.write("<-:->") + showProblemErrors() + +@CmdLine("b") +def showProblemErrors(): + """ + Show unexpected errors inside errors.txt + """ + with (examplePath / "errors.txt").open() as errors_txt: + for err in errors_txt.read().split("<-:->"): + if "_[ logging\\" in err: + continue + if "LoggingException" in err: + continue + if "---[ Exception is Expected ]---" in err: + continue + print(err) + @CmdLine("a") diff --git a/tools/update_git.py b/tools/update_git.py index f87d4e1f..b70dd941 100644 --- a/tools/update_git.py +++ b/tools/update_git.py @@ -1,6 +1,7 @@ #! Py -3 from pathlib import Path from filecmp import cmpfiles +from filecmp import dircmp import sys, os from sortedcontainers import SortedSet from betools import * @@ -43,17 +44,41 @@ def retain(lst): result = [f for f in result if not str(f).endswith(k)] return result +def print_diff_files(dcmp): + for name in dcmp.diff_files: + print("diff_file %s found in %s and %s" % (name, dcmp.left, dcmp.right)) + for sub_dcmp in dcmp.subdirs.values(): + print_diff_files(sub_dcmp) + @CmdLine('x') def clean(): - "Write batch file to remove unused files from git directory" - os.chdir(str(gitpath)) - with Path("clean.bat").open("w") as clean: - toclean = retain([g for g in git if g not in book]) - for tc in toclean: - clean.write("del " + str(tc) + "\n") - if Path("clean.bat").stat().st_size == 0: - Path("clean.bat").unlink() + "Show differences with git directory" + os.chdir(str(examplePath)) + os.system("diff -q -r . " + str(gitpath)) + # common = [str(b) for b in book if not b.is_dir()] + # dcmp = dircmp(str(examplePath), str(gitpath)) + # print_diff_files(dcmp) + # print(dcmp.right_only) + # with Path("clean.bat").open('w') as outfile: + # outfile.write("\n" + ruler("match")) + # outfile.write(pformat(match)) + # outfile.write("\n" + ruler("mismatch")) + # outfile.write(pformat(mismatch)) + # outfile.write("\n" + ruler("errors")) + # outfile.write(pformat(errors)) + # head("files to update") + # for f in mismatch: + # outfile.write("copy {} {}\{}\n".format(f, str(gitpath), f)) + # print(f) + + # os.chdir(str(gitpath)) + # with Path("clean.bat").open("w") as clean: + # toclean = retain([g for g in git if g not in book]) + # for tc in toclean: + # clean.write("del " + str(tc) + "\n") + # if Path("clean.bat").stat().st_size == 0: + # Path("clean.bat").unlink() @CmdLine('u') def update_to_git():