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

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

#112 commit before trying to run new zip()

File size: 5.6 KB
Line 
1package tudelft.utilities.j2p;
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.util.Arrays;
13import java.util.LinkedList;
14import java.util.List;
15
16import com.github.javaparser.JavaParser;
17import com.github.javaparser.ParseResult;
18import com.github.javaparser.ParserConfiguration;
19import com.github.javaparser.ast.CompilationUnit;
20import com.github.javaparser.symbolsolver.JavaSymbolSolver;
21import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
22import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
23
24import tudelft.utilities.j2p.formatting.Block;
25import tudelft.utilities.j2p.t.Translator;
26import tudelft.utilities.pyrunner.Call;
27import tudelft.utilities.pyrunner.PythonError;
28import tudelft.utilities.pyrunner.PythonVenv;
29
30public class PyTest {
31 private static final String TESTFILE = "test.py";
32 private static final File TESTDIR = new File("test/");
33
34 /**
35 *
36 * @param pycode the python code to run.
37 * @param fullclaspath a "package/class/path/filename.py" name containing
38 * the full filename where the file should be placed.
39 * This must be a RELATIVE name, we will prefix it with
40 * {@link #TESTDIR} as needed
41 * @return the text lines that the code printed to stdout.
42 * @throws Exception
43 */
44 public List<String> runPython(Block pycode, String fullclaspath)
45 throws Exception {
46 TESTDIR.delete();
47 File f = TESTDIR.toPath().resolve(fullclaspath).toFile();
48 f.getParentFile().mkdirs();// create dir, massaging java...
49 FileOutputStream fos = new FileOutputStream(f);
50 BufferedOutputStream bos = new BufferedOutputStream(fos);
51 // convert string to byte array
52 byte[] bytes = pycode.toString().getBytes();
53 // write byte array to file
54 bos.write(bytes);
55 bos.close();
56 fos.close();
57
58 Process process = Runtime.getRuntime().exec("python " + fullclaspath,
59 new String[0], TESTDIR);
60 List<String> errors = readAll(process.getErrorStream());
61 if (!errors.isEmpty())
62 throw new IllegalStateException("Python failed. " + errors);
63
64 return readAll(process.getInputStream());
65 }
66
67 /**
68 *
69 * @param pycode the python code to be zipped
70 * @param modulename The name of the module. It is assumed there is just 1
71 * module, and this module is also a directory in the root
72 * folder, and only 1 level deep. The main program must be
73 * in this module. FIXME should be in pycode.
74 * @return a zip {@link File} containing all the code, as a python tar.gz
75 * package that can be pip install'ed .
76 * @throws IOException
77 * @throws PythonError if python code to build tar.gz fails for
78 * some reason
79 * @throws InterruptedException
80 */
81 public File zip(Block pycode, String modulename)
82 throws IOException, InterruptedException, PythonError {
83 TESTDIR.delete();
84 File f = TESTDIR.toPath().resolve(modulename).toFile();
85 f.getParentFile().mkdirs();// create dir, massaging java...
86 FileOutputStream fos = new FileOutputStream(f);
87 BufferedOutputStream bos = new BufferedOutputStream(fos);
88 // convert string to byte array
89 byte[] bytes = pycode.toString().getBytes();
90 // write byte array to file
91 bos.write(bytes);
92 bos.close();
93 fos.close();
94
95 String requirements = String.join(",\n", pycode.getInstalls());
96 String setuppy = "from setuptools import setup, find_packages\n" + "\n"
97 + " version=1,\n" + "setup(\n" + " name='" + modulename
98 + "',\n" + " py_modules=['" + modulename + "'],\n"
99 + " install_requires=[ \n" + requirements + " ],\n"
100 + "\n" + " classifiers=[\n"
101 + " 'Programming Language :: Python :: 3.8',\n"
102 + " 'Programming Language :: Python :: 3.9'\n"
103 + " ],\n" + ")\n" + "";
104
105 f = TESTDIR.toPath().resolve("setup.py").toFile();
106 FileWriter fw = new FileWriter(f);
107 fw.write(setuppy);
108 fw.close();
109
110 // call python to build the package to be sure we have a correct package
111 new Call(PythonVenv.PYTHON3, Arrays.asList("setup.py", "sdist"), 30000)
112 .run();
113
114 // -1 is the version number added py setup.py to the file
115 return TESTDIR.toPath().resolve("dist/" + modulename + "-1.tar.gz")
116 .toFile();
117 }
118
119 private List<String> readAll(InputStream in) throws IOException {
120 BufferedReader Buffered_Reader = new BufferedReader(
121 new InputStreamReader(in));
122 List<String> lines = new LinkedList<>();
123
124 String line;
125 while ((line = Buffered_Reader.readLine()) != null) {
126 lines.add(line);
127 }
128 return lines;
129 }
130
131 /**
132 * @param javaFile a java file name to be translated
133 * @return a string containing python code translated from the java.
134 * @throws FileNotFoundException
135 */
136 public Block translate(String javaFile) throws FileNotFoundException {
137 ParserConfiguration conf = new ParserConfiguration();
138 CombinedTypeSolver typeSolver = new CombinedTypeSolver();
139 typeSolver.add(new ReflectionTypeSolver(false));
140 // FIXME add sources of jars source code etc
141 // typeSolver.add(new JavaParserTypeSolver(new File(SOURCE_PATH)));
142 // typeSolver.add(new JarTypeSolver(jarSourceFile));
143 JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver);
144 conf.setSymbolResolver(symbolSolver);
145 JavaParser parser = new JavaParser(conf);
146
147 ParseResult<CompilationUnit> res = parser.parse(new File(javaFile));
148
149 Block translation = new Translator().translate(res.getResult().get());
150 return translation;
151 }
152
153}
Note: See TracBrowser for help on using the repository browser.