Skip to content

Commit

Permalink
addressed some regression on this unit test. refactored reflect_class…
Browse files Browse the repository at this point in the history
…() on the case of duplicate methods
  • Loading branch information
cmacdonald committed Jun 4, 2020
1 parent 17e264c commit 4ef1593
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 16 deletions.
30 changes: 19 additions & 11 deletions jnius/reflect.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,15 +350,7 @@ def reflect_class(cls_object, include_protected=_DEFAULT_INCLUDE_PROTECTED, incl
get_signature(method.getReturnType()))
if log.isEnabledFor(DEBUG):
log_method(method, name, sig)
classDict[name] = (JavaStaticMethod if static else JavaMethod)(sig, varargs=varargs)
# methods that fit the characteristics of a JavaBean's methods get turned into properties.
# these added properties should not supercede any other methods or fields.
if name != 'getClass' and bean_getter(name) and len(method.getParameterTypes()) == 0:
lowername = lower_name(name[2 if name.startswith('is') else 3:])
if lowername in classDict:
# don't add this to classDict if the property will replace a method or field.
continue
classDict[lowername] = (lambda n: property(lambda self: getattr(self, n)()))(name)
_add_single_method(classDict, name, static, sig, varargs)
else:
# multiple signatures
signatures = []
Expand Down Expand Up @@ -387,8 +379,14 @@ def reflect_class(cls_object, include_protected=_DEFAULT_INCLUDE_PROTECTED, incl
log_method(method, name, sig)
signatures.append((sig, Modifier.isStatic(method.getModifiers()), method.isVarArgs()))

log.debug("method selected %d multiple signatures of %s" % (len(signatures), str(signatures)))
classDict[name] = JavaMultipleMethod(signatures)
if len(signatures) > 1:
log.debug("method selected %d multiple signatures of %s" % (len(signatures), str(signatures)))
classDict[name] = JavaMultipleMethod(signatures)
elif len(signatures) == 1:
(sig, static, varargs) = signatures[0]
if log.isEnabledFor(DEBUG):
log_method(method, name, sig)
_add_single_method(classDict, name, static, sig, varargs)

# check whether any classes in the hierarchy appear in the protocol_map
for cls, _ in class_hierachy:
Expand All @@ -405,6 +403,16 @@ def reflect_class(cls_object, include_protected=_DEFAULT_INCLUDE_PROTECTED, incl
classDict,
classparams=(include_protected, include_private))

def _add_single_method(classDict, name, static, sig, varargs):
classDict[name] = (JavaStaticMethod if static else JavaMethod)(sig, varargs=varargs)
# methods that fit the characteristics of a JavaBean's methods get turned into properties.
# these added properties should not supercede any other methods or fields.
if name != 'getClass' and bean_getter(name) and sig.startswith("()"):
lowername = lower_name(name[2 if name.startswith('is') else 3:])
if lowername in classDict:
# don't add this to classDict if the property will replace a method or field.
return
classDict[lowername] = (lambda n: property(lambda self: getattr(self, n)()))(name)

def _getitem(self, index):
''' dunder method for List '''
Expand Down
10 changes: 5 additions & 5 deletions tests/test_visibility_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,21 +216,21 @@ def assert_is_method(obj, name):
def test_check_method_vs_property(self):
"""check that "bean" properties don't replace methods.
The ExecutorService Interface has methods `shutdown()`, `isShutdown()`,
`isTerminated()`. The `autoclass` function will create a Python
The ExecutorService Interface has methods `shutdown()`, `isShutdown()`,
`isTerminating()`. The `autoclass` function will create a Python
`property` if a function name matches a JavaBean name pattern. Those
properties are important but they should not take priority over a
method.
For this Interface it wants to create properties called `shutdown` and
`terminated` because of `isShutdown` and `isTerminated`. A `shutdown`
`terminating` because of `isShutdown` and `isTerminating`. A `shutdown`
property would conflict with the `shutdown()` method so it should be
skipped. The `terminated` property is OK though.
skipped. The `terminating` property is OK though.
"""
executor = autoclass("java.util.concurrent.Executors")
pool = executor.newFixedThreadPool(1)

self.assertTrue(isinstance(pool.__class__.__dict__['shutdown'], JavaMethod))
self.assertTrue(isinstance(pool.__class__.__dict__['terminated'], property))
self.assertTrue(isinstance(pool.__class__.__dict__['terminating'], property))
self.assertTrue(isinstance(pool.__class__.__dict__['isShutdown'], JavaMethod))
self.assertTrue(isinstance(pool.__class__.__dict__['isTerminated'], JavaMethod))

0 comments on commit 4ef1593

Please sign in to comment.