Skip to content

Commit 9b809f7

Browse files
committed
[GR-73854] Document and make work adding arguments to __init__ when subclassing from Java.
PullRequest: graalpython/4293
2 parents 39cda33 + 063c9e5 commit 9b809f7

3 files changed

Lines changed: 27 additions & 7 deletions

File tree

docs/user/Python-on-JVM.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,10 @@ assert issubclass(PythonLevel, Level)
333333
assert PythonLevel.parse("INFO").getName() == "INFO"
334334
```
335335

336+
Two important caveats:
337+
338+
1. You cannot use other metaclasses, so inheriting from `ABC` and a Java class is not supported.
339+
2. If you want to implement `__init__` to accept additional arguments, you must also override `__new__` to avoid passing the additional arguments to the Java constructor, which would not know how to handle them.
336340

337341
## Embedding Python into Java
338342

graalpython/com.oracle.graal.python.test/src/tests/test_interop.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ class MyHandler (Handler):
675675
counter = 0;
676676
def isLoggable(self, logrecord):
677677
self.counter = self.counter + 1
678-
return self.__super__.isLoggable(logrecord)
678+
return super().isLoggable(logrecord)
679679
def sayHello(self):
680680
return 'Hello'
681681

@@ -726,9 +726,9 @@ def test_extend_java_class_03(self):
726726

727727
class MyLogRecord(LogRecord):
728728
def getLevel(self):
729-
if self.__super__.getLevel() == Level.FINEST:
730-
self.__super__.setLevel(Level.WARNING)
731-
return self.__super__.getLevel()
729+
if super().getLevel() == Level.FINEST:
730+
super().setLevel(Level.WARNING)
731+
return super().getLevel()
732732

733733
message = "log message"
734734
my_lr1 = MyLogRecord(Level.WARNING, message)
@@ -1503,6 +1503,18 @@ def getName(self):
15031503
assert pl.callStaticFromPython("INFO").getName() == "INFO"
15041504
assert PythonLevel2.parse("INFO").getName() == "INFO"
15051505

1506+
def test_java_subclassing_with_new_arguments(self):
1507+
from java.util.logging import Level
1508+
1509+
class PythonLevel(Level, new_style=True):
1510+
def __new__(cls, misc_value):
1511+
return super().__new__(cls, "default name", 2)
1512+
1513+
def __init__(self, misc_value):
1514+
self.misc_value = misc_value
1515+
1516+
pl = PythonLevel(123)
1517+
assert pl.misc_value == 123
15061518

15071519
def test_jython_star_import(self):
15081520
if __graalpython__.jython_emulation_enabled:

graalpython/lib-graalpython/__graalpython__.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -98,7 +98,7 @@ def import_current_as_named_module_with_delegate(module, module_name, delegate_n
9898

9999

100100
@builtin
101-
def build_java_class(module, ns, name, base, new_style=False):
101+
def build_java_class(module, ns, name, base, new_style=True):
102102
if new_style:
103103
return build_new_style_java_class(ns, name, base)
104104
import warnings
@@ -174,6 +174,11 @@ def __instancecheck__(cls, obj):
174174
def __subclasscheck__(cls, derived):
175175
return cls is derived or issubclass(derived, JavaClass)
176176

177+
def __call__(cls, *args, **kwds):
178+
java_object = cls.__new__(cls, *args, **kwds)
179+
java_object.this.__init__(*args, **kwds)
180+
return java_object
181+
177182
def __new__(mcls, name, bases, namespace):
178183
if bases:
179184
new_class = None
@@ -232,7 +237,6 @@ def __new__(cls, *args, **kwds):
232237
delegate = object.__new__(cls)
233238
java_object = polyglot.__new__(JavaClass, *(args + (delegate,)))
234239
delegate.__this__ = java_object
235-
delegate.__init__(*args, **kwds)
236240
return java_object
237241

238242
return type(name, (DelegateSuperclass,), ns)

0 commit comments

Comments
 (0)