1 | package tudelft.utilities.j2p;
|
---|
2 |
|
---|
3 | import java.io.BufferedOutputStream;
|
---|
4 | import java.io.BufferedReader;
|
---|
5 | import java.io.File;
|
---|
6 | import java.io.FileNotFoundException;
|
---|
7 | import java.io.FileOutputStream;
|
---|
8 | import java.io.FileWriter;
|
---|
9 | import java.io.IOException;
|
---|
10 | import java.io.InputStream;
|
---|
11 | import java.io.InputStreamReader;
|
---|
12 | import java.util.Arrays;
|
---|
13 | import java.util.LinkedList;
|
---|
14 | import java.util.List;
|
---|
15 |
|
---|
16 | import com.github.javaparser.JavaParser;
|
---|
17 | import com.github.javaparser.ParseResult;
|
---|
18 | import com.github.javaparser.ParserConfiguration;
|
---|
19 | import com.github.javaparser.ast.CompilationUnit;
|
---|
20 | import com.github.javaparser.symbolsolver.JavaSymbolSolver;
|
---|
21 | import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
|
---|
22 | import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
|
---|
23 |
|
---|
24 | import tudelft.utilities.j2p.formatting.Block;
|
---|
25 | import tudelft.utilities.j2p.t.Translator;
|
---|
26 | import tudelft.utilities.pyrunner.Call;
|
---|
27 | import tudelft.utilities.pyrunner.PythonError;
|
---|
28 | import tudelft.utilities.pyrunner.PythonVenv;
|
---|
29 |
|
---|
30 | public 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 | }
|
---|