1 #!/usr/bin/env python 2 3 """ 4 Wrap Java packages, converting the skeleton Java classes to Python modules which 5 connect to concrete Python implementation classes. 6 """ 7 8 import classfile 9 import glob 10 import sys 11 import os 12 13 if __name__ == "__main__": 14 if len(sys.argv) < 2: 15 print "wrap.py <package directory> <wrapped package>" 16 print "For example:" 17 print "wrap.py qtjava qt" 18 sys.exit(1) 19 20 # Process all directories in the list, producing for each a Python source 21 # file containing the classes found in the given directory. 22 23 directory, package = sys.argv[1:3] 24 f = open(os.path.join(directory, "__init__.py"), "w") 25 f.write("import %s\n" % package) 26 f.write("import java.lang\n") 27 28 # Process each class file. 29 30 for filename in glob.glob(os.path.join(directory, "*.class")): 31 print "Processing", filename 32 cf = open(filename, "rb") 33 c = classfile.ClassFile(cf.read()) 34 cf.close() 35 36 # Write the class into the source file. 37 38 full_name = c.this_class.get_python_name() 39 class_name = full_name.split(".")[-1] 40 f.write("class %s(%s.%s, java.lang.Object):\n" % (class_name, package, class_name)) 41 42 # Process methods in the class, writing wrapper code. 43 44 method_names = [] 45 for method in c.methods: 46 wrapped_method_name = method.get_unqualified_python_name() 47 48 # Find out more about the parameters, introducing special 49 # conversions where appropriate. 50 51 parameter_names = ["self"] 52 parameter_index = 1 53 conversions = [] 54 55 for parameter in method.get_descriptor()[0]: 56 parameter_name = "p" + str(parameter_index) 57 base_type, object_type, array_type = parameter 58 59 # Special cases. 60 61 if object_type == "java/lang/String": 62 conversions.append("%s = unicode(%s)" % (parameter_name, parameter_name)) 63 # elif object_type == "java/util/Map": 64 # NOTE: Using special private interface. 65 # conversions.append("%s = %s.as_dict()" % (parameter_name, parameter_name)) 66 67 parameter_names.append(parameter_name) 68 parameter_index += 1 69 70 # Write the signature. 71 72 f.write(" def %s(%s):\n" % (wrapped_method_name, ", ".join(parameter_names))) 73 74 # Write any conversions. 75 76 for conversion in conversions: 77 f.write(" %s\n" % conversion) 78 79 # Write the call to the wrapped method. 80 81 f.write(" return %s.%s.%s(%s)\n" % (package, class_name, wrapped_method_name, ", ".join(parameter_names))) 82 83 # Record the correspondence between the Java-accessible and wrapped 84 # method names. 85 86 method_name = method.get_python_name() 87 method_names.append((method_name, wrapped_method_name)) 88 89 # Produce method entries for the specially named methods. 90 91 for method_name, wrapped_method_name in method_names: 92 f.write("setattr(%s, '%s', %s.%s)\n" % (class_name, method_name, class_name, wrapped_method_name)) 93 94 # Remove the original class. 95 96 print "Removing", filename 97 os.remove(filename) 98 99 f.close() 100 101 # vim: tabstop=4 expandtab shiftwidth=4