source: java2python/src/test/java/tudelft/utilities/j2p/t/PyTest.java@ 383

Last change on this file since 383 was 383, checked in by wouter, 2 years ago

#115 numerous fixes: UniaryExpression, String.matches, throws, etc. ActionTest now compiles

File size: 6.4 KB
Line 
1package tudelft.utilities.j2p.t;
2
3import java.io.BufferedOutputStream;
4import java.io.BufferedReader;
5import java.io.File;
6import java.io.FileNotFoundException;
7import java.io.FileOutputStream;
8import java.io.FileWriter;
9import java.io.IOException;
10import java.io.InputStream;
11import java.io.InputStreamReader;
12import java.nio.file.Files;
13import java.nio.file.Path;
14import java.util.Arrays;
15import java.util.LinkedList;
16import java.util.List;
17
18import com.github.javaparser.JavaParser;
19import com.github.javaparser.ParseResult;
20import com.github.javaparser.ParserConfiguration;
21import com.github.javaparser.ast.CompilationUnit;
22import com.github.javaparser.symbolsolver.JavaSymbolSolver;
23import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
24import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
25
26import tudelft.utilities.j2p.formatting.Block;
27import tudelft.utilities.pyrunner.Call;
28import tudelft.utilities.pyrunner.PythonError;
29import tudelft.utilities.pyrunner.PythonVenv;
30
31public class PyTest {
32 private static final String TESTFILE = "test.py";
33 private static final File TESTDIR = new File("test/");
34
35 /**
36 * Run the program as plain file. Installs are ignored so only usable if the
37 * code only uses basic system calls
38 *
39 * @param pycode the python code to run.
40 * @param fullclaspath a "package/class/path/filename.py" name containing
41 * the full filename where the file should be placed.
42 * This must be a RELATIVE name, we will prefix it with
43 * {@link #TESTDIR} as needed
44 * @return the text lines that the code printed to stdout.
45 * @throws Exception
46 */
47 public List<String> runPython(Block pycode, String fullclaspath)
48 throws Exception {
49 TESTDIR.delete();
50 File f = TESTDIR.toPath().resolve(fullclaspath).toFile();
51 System.out.println(f);
52 f.getParentFile().mkdirs();// create dir, massaging java...
53 FileOutputStream fos = new FileOutputStream(f);
54 BufferedOutputStream bos = new BufferedOutputStream(fos);
55 // convert string to byte array
56 byte[] bytes = pycode.toCode(
57 "from " + fullclaspath.replace("/", "\\.").replace(".py", "")
58 + " import .*")
59 .getBytes();
60 // write byte array to file
61 bos.write(bytes);
62 bos.close();
63 fos.close();
64
65 Process process = Runtime.getRuntime().exec("python " + fullclaspath,
66 new String[0], TESTDIR);
67 List<String> errors = readAll(process.getErrorStream());
68 if (!errors.isEmpty())
69 throw new IllegalStateException("Python failed. " + errors);
70
71 return readAll(process.getInputStream());
72 }
73
74 private List<String> readAll(InputStream in) throws IOException {
75 BufferedReader Buffered_Reader = new BufferedReader(
76 new InputStreamReader(in));
77 List<String> lines = new LinkedList<>();
78
79 String line;
80 while ((line = Buffered_Reader.readLine()) != null) {
81 lines.add(line);
82 }
83 return lines;
84 }
85
86 /**
87 *
88 * @param pycode the python code to be zipped as pip-installable zip.
89 * It is assumed that the code is just 1 file.
90 * @param fullpathname the java file that was translated..
91 * @return a zip {@link File} containing all the code, as a python tar.gz
92 * package that can be pip install'ed .
93 * @throws IOException
94 * @throws PythonError if python code to build tar.gz fails for
95 * some reason
96 * @throws InterruptedException
97 */
98 public File zip(Block pycode, File fullpathname)
99 throws IOException, InterruptedException, PythonError {
100
101 Path tmppath = Files.createTempDirectory("j2p");
102 System.out.println(tmppath);
103
104 String baremodule = fullpathname.getPath().replace(".java", "");
105 String modulename = baremodule + ".py";
106 String version = "1";
107
108 // write the translated file
109 File f = tmppath.resolve(modulename).toFile();
110 f.getParentFile().mkdirs();// create dirs
111 FileOutputStream fos = new FileOutputStream(f);
112 BufferedOutputStream bos = new BufferedOutputStream(fos);
113 // convert string to byte array
114 byte[] bytes = pycode
115 .toCode("from " + baremodule.replace("/", ".") + " import .*")
116 .getBytes();
117 // write byte array to file
118 bos.write(bytes);
119 bos.close();
120 fos.close();
121
122 String zipname = fullpathname.getName().replace(".java", "");
123
124 List<String> requirements = pycode.getInstalls().stream()
125 .map(str -> "\"" + str + "\"").toList();
126 // we must provide many nonsense fields like url and author to get this
127 // working...
128 String setuppy = "from setuptools import setup, find_packages\n" + "\n"
129 + "setup(\n" + " name='" + zipname + "',\n" + " version="
130 + version + ",\n" + " author='Whatever',\n"
131 + " author_email='Whatever',\n"
132 + " url='http://nonsense',\n" + " py_modules=['"
133 + baremodule + "'],\n" + " install_requires=" + requirements
134 + ",\n" + "\n" + " classifiers=[\n"
135 + " 'Programming Language :: Python :: 3.8',\n"
136 + " 'Programming Language :: Python :: 3.9'\n"
137 + " ],\n" + ")\n" + "";
138
139 f = tmppath.resolve("setup.py").toFile();
140 FileWriter fw = new FileWriter(f);
141 fw.write(setuppy);
142 fw.close();
143
144 // without readme, python complains
145 f = tmppath.resolve("README").toFile();
146 fw = new FileWriter(f);
147 fw.write("");
148 fw.close();
149
150 // call python to build the package to be sure we have a correct package
151 new Call(PythonVenv.PYTHON3, Arrays.asList("setup.py", "sdist"), 30000,
152 tmppath.toFile()).run();
153
154 // -1 is the version number added py setup.py to the file
155 return tmppath.resolve("dist/" + zipname + "-" + version + ".tar.gz")
156 .toFile();
157 }
158
159 /**
160 * @param javaFile a java file name to be translated
161 * @return a string containing python code translated from the java.
162 * @throws FileNotFoundException
163 */
164 public Block translate(String javaFile) throws FileNotFoundException {
165 ParserConfiguration conf = new ParserConfiguration();
166 CombinedTypeSolver typeSolver = new CombinedTypeSolver();
167 typeSolver.add(new ReflectionTypeSolver(false));
168 // FIXME add sources of jars source code etc
169 // typeSolver.add(new JavaParserTypeSolver(new File(SOURCE_PATH)));
170 // typeSolver.add(new JarTypeSolver(jarSourceFile));
171 JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver);
172 conf.setSymbolResolver(symbolSolver);
173 JavaParser parser = new JavaParser(conf);
174
175 ParseResult<CompilationUnit> res = parser.parse(new File(javaFile));
176// fixparseissues(res.getResult().get());
177
178 Block translation = Translator.translate(res.getResult().get());
179 return translation;
180 }
181
182}
Note: See TracBrowser for help on using the repository browser.