/jstubgen

Python type hint stub generator for Java classes. Just a POC for now!

Primary LanguagePython

Currently a POC to demonstrate the feasibility of generating type hints from Java classes to be used by MyPy and other Python type checkers.

Next steps:

  • Add support for generics from the full type signature of the method, instead of using Any (especially noticeable for container types like HashMap below).

  • Callable, etc, take parameters. Get these out of Java.

  • Union constructor/method overloading as used by Java so that only one __init__ method, etc is generated

  • Test against MyPy 2.7 support

  • Test against Jython 3.x code (necessary for full support of Python type functionality). Obviously this would be be best with a working Jython 3.x implemengtation, however since such code is, with a couple of exceptions, always legal Python 3.x code, this can be done using MyPy's existing static analysis support.

  • Obvious engineering improvements, again this is currently just a quick POC to show feasibility!

To run, you need to ensure the ASM 7.2 library jar is on your CLASSPATH; this can also be readily done if you are using a dev build of Jython, which doesn't move the org.objectweb.asm namespace into org.python.

Example:

$ jython jstubgen-poc.py java.util.HashMap
class HashMap(java.util.AbstractMap, java.util.Map, java.lang.Cloneable, java.io.Serializable):
  def __init__(self, initialCapacity: int, loadFactor: float) -> None: ...
  def __init__(self, initialCapacity: int) -> None: ...
  def __init__(self) -> None: ...
  def __init__(self, m: Map) -> None: ...
  def size(self) -> int: ...
  def isEmpty(self) -> bool: ...
  def get(self, key: Any) -> Any: ...
  def containsKey(self, key: Any) -> bool: ...
  def put(self, key: Any, value: Any) -> Any: ...
  def putAll(self, m: Map) -> None: ...
  def remove(self, key: Any) -> Any: ...
  def clear(self) -> None: ...
  def containsValue(self, value: Any) -> bool: ...
  def keySet(self) -> Set: ...
  def values(self) -> Collection: ...
  def entrySet(self) -> Set: ...
  def getOrDefault(self, key: Any, defaultValue: Any) -> Any: ...
  def putIfAbsent(self, key: Any, value: Any) -> Any: ...
  def remove(self, key: Any, value: Any) -> bool: ...
  def replace(self, key: Any, oldValue: Any, newValue: Any) -> bool: ...
  def replace(self, key: Any, value: Any) -> Any: ...
  def computeIfAbsent(self, key: Any, mappingFunction: Callable) -> Any: ...
  def computeIfPresent(self, key: Any, remappingFunction: Callable) -> Any: ...
  def compute(self, key: Any, remappingFunction: Callable) -> Any: ...
  def merge(self, key: Any, value: Any, remappingFunction: Callable) -> Any: ...
  def forEach(self, action: Callable) -> None: ...
  def replaceAll(self, function: Callable) -> None: ...
  def clone(self) -> Any: ...