Skip to content

Commit

Permalink
Convert JInterface to Meta class.
Browse files Browse the repository at this point in the history
  • Loading branch information
Thrameos committed Jan 20, 2020
1 parent b19e984 commit d8323e7
Show file tree
Hide file tree
Showing 12 changed files with 370 additions and 428 deletions.
2 changes: 2 additions & 0 deletions doc/CHANGELOG.rst
Expand Up @@ -5,6 +5,8 @@ This changelog *only* contains changes from the *first* pypi release (0.5.4.3) o

- **Next version - unreleased**

- JInterface is now a meta class. Use isinstance(cls, JInterface)
to test for interfaces.

- **0.7.1 - 12-16-2019**

Expand Down
58 changes: 19 additions & 39 deletions jpype/_jclass.py
Expand Up @@ -196,10 +196,6 @@ def mro(cls):
# Include the remaining that we still need to consider
parents.extend([b for b in prev if not b in parents])

# JavaObjects are not interfaces, so we need to remove the JavaInterface inheritance
if _JObject in out and JInterface in out:
out.remove(JInterface)

return out

def __repr__(self):
Expand Down Expand Up @@ -250,51 +246,35 @@ def _JClassNew(arg, loader=None, initialize=True):
return cls


class JInterface(object):
"""Base class for all Java Interfaces.
class JInterfaceMeta(type):
def __instancecheck__(self, obj):
if not hasattr(obj, '__javaclass__'):
return False
return obj.__javaclass__.isInterface()

def __subclasscheck__(self, obj):
# This is included for compatiblity with JPype 0.7.x
if not hasattr(obj, '__javaclass__'):
return False
return obj.__javaclass__.isInterface()

``JInterface`` is serves as the base class for any java class that is
class JInterface(metaclass=JInterfaceMeta):
"""A meta class for all Java Interfaces.
``JInterface`` is serves as the base class for any Java class that is
a pure interface without implementation. It is not possible to create
a instance of a java interface. The ``mro`` is hacked such that
``JInterface`` does not appear in the tree of objects implement an
interface.
a instance of a Java interface.
Example:
.. code-block:: python
if issubclass(java.util.function.Function, jpype.JInterface):
if isinstance(java.util.function.Function, jpype.JInterface):
print("is interface")
Use ``isinstance(obj, jpype.JavaInterface)`` to test for a interface.
"""
@property
def class_(self):
return _JObject(self.__javaclass__)

def __new__(cls, *args, **kwargs):
return super(JInterface, cls).__new__(cls)

def __init__(self, *args, **kwargs):
if len(args) == 1 and isinstance(args[0], _jpype.PyJPValue):
object.__setattr__(self, '__javavalue__', args[0])
elif not hasattr(self, '__javavalue__'):
raise JClass("java.lang.InstantiationException")(
"`%s` is an interface." % str(self.class_.getName()))
super(JInterface, self).__init__()

def __str__(self):
return self.toString()

def __hash__(self):
return self.hashCode()

def __eq__(self):
return self.equals(o)

def __ne__(self):
return not self.equals(o)
pass


def _JClassFactory(name, jc):
Expand All @@ -312,7 +292,7 @@ def _JClassFactory(name, jc):
elif bjc is not None:
bases.append(JClass(bjc))
elif bjc is None:
bases.append(JInterface)
bases.append(_JObject)
itf = jc.getInterfaces()
for ic in itf:
bases.append(JClass(ic))
Expand Down
3 changes: 3 additions & 0 deletions jpype/_jcomparable.py
Expand Up @@ -41,3 +41,6 @@ def __ge__(self, o):

def __le__(self, o):
return self.compareTo(o) <= 0

def __hash__(self):
return self.hashCode()
45 changes: 45 additions & 0 deletions native/build_coverage.xml
@@ -0,0 +1,45 @@
<project default="all" name="JPype - Native">

<!-- JAVA_VERSION must match the oldest supported Java version -->
<property name="JAVA_VERSION" value="8" />

<!-- src can't be "java" as it breaks nose tests -->
<property name="src" location="java"/>
<property name="build" location="build"/>

<target name="test" depends="compile">
</target>

<target name="compile">
<mkdir dir="${build}/classes"/>
<mkdir dir="${build}/lib"/>
<javac destdir="${build}/classes"
source="${JAVA_VERSION}"
target="${JAVA_VERSION}"
excludes="**/JPypeClassLoader.java"
debug="true"
debuglevel="source,lines,vars"
>
<src path="${src}"/>
</javac>
<javac destdir="${build}/lib"
source="${JAVA_VERSION}"
target="${JAVA_VERSION}"
includes="**/JPypeClassLoader.java"
>
<src path="${src}"/>
</javac>
</target>

<target name="jar" depends="compile">
<jar destfile="native/org.jpype.jar"
basedir="${build}/classes" />
</target>

<target name="all" depends="jar" />

<target name="clean">
<delete dir="${build}"/>
</target>

</project>
11 changes: 10 additions & 1 deletion native/python/include/pyjp.h
Expand Up @@ -38,7 +38,6 @@
*/
#include <pyjp_module.h>
#include <pyjp_array.h>
#include <pyjp_class.h>
#include <pyjp_field.h>
#include <pyjp_method.h>
#include <pyjp_module.h>
Expand All @@ -51,6 +50,12 @@ extern "C"
{
#endif

struct PyJPClass
{
PyObject_HEAD
JPClass* m_Class;
} ;

struct PyJPProxy
{
PyObject_HEAD
Expand All @@ -60,6 +65,8 @@ struct PyJPProxy
} ;

extern PyTypeObject* PyJPProxy_Type;
extern PyTypeObject* PyJPClass_Type;


#ifdef __cplusplus
}
Expand All @@ -68,4 +75,6 @@ extern PyTypeObject* PyJPProxy_Type;
#define ASSERT_JVM_RUNNING(X) JPEnv::assertJVMRunning(X, JP_STACKINFO())
#define PY_STANDARD_CATCH catch(...) { JPPythonEnv::rethrow(JP_STACKINFO()); }

JPPyObject PyJPClass_alloc(JPClass* cls);

#endif /* PYJP_H */
71 changes: 0 additions & 71 deletions native/python/include/pyjp_class.h

This file was deleted.

6 changes: 3 additions & 3 deletions native/python/jp_pythonenv.cpp
Expand Up @@ -82,7 +82,7 @@ JPPyObject JPPythonEnv::newJavaClass(JPClass* javaClass)

JP_TRACE(javaClass->toString());
JPPyTuple args(JPPyTuple::newTuple(1));
args.setItem(0, PyJPClass::alloc(javaClass).get());
args.setItem(0, PyJPClass_alloc(javaClass).get());

// calls jpype._jclass._getClassFor(_jpype.PyJPClass)
if (s_Resources->s_GetClassMethod.isNull())
Expand Down Expand Up @@ -112,12 +112,12 @@ JPValue* JPPythonEnv::getJavaValue(PyObject* obj)
JPClass* JPPythonEnv::getJavaClass(PyObject* obj)
{
JPPyObject vobj(JPPyRef::_use, obj);
if (Py_TYPE(obj) == &PyJPClass::Type)
if (Py_TYPE(obj) == PyJPClass_Type)
return ((PyJPClass*) obj)->m_Class;
if (!JPPyObject::hasAttrString(obj, __javaclass__))
return NULL;
JPPyObject self(JPPyObject::getAttrString(obj, __javaclass__));
if (Py_TYPE(self.get()) == &PyJPClass::Type)
if (Py_TYPE(self.get()) == PyJPClass_Type)
{
return ((PyJPClass*) self.get())->m_Class;
}
Expand Down

0 comments on commit d8323e7

Please sign in to comment.