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

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

#116 various fixes, to support multi-file zips

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