1

I am building a text editor with Jython using Java Swing. I have come across CompoundEdit, a Swing class that has a list of edit actions from a text editor. This attribute is protected, which means that I can't access it directly from another class, but I can from other classes that extend it. So, if I create a MyEdit class that extends CompoundEdit, MyEdit should have access to the list of edits.

This is what I'm trying:

class MyEdit(CompoundEdit):
    def __init__(self):
        super(CompoundEdit, self).__init__()
        print(dir(self)) # Doesn't show the edits
        self.nammu_edits = super(CompoundEdit, self).edits 

Running this gives me this error:

AttributeError: 'super' object has no attribute 'edits'

For reference, this is what dir comes back with:

['__class__', '__copy__', '__deepcopy__', '__delattr__', '__dict__', '__doc__', '__ensure_finalizer__', '__eq__', '__format__', '__getattribute__', '__hash__', '__initProxy__', '__init__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__subclasshook__', '__supernames__', '__unicode__', '__weakref__', '_getPyInstance', '_getPySystemState', '_setPyInstance', '_setPySystemState', 'addEdit', 'canRedo', 'canUndo', 'class', 'classDictInit', 'clone', 'die', 'doPrint', 'end', 'equals', 'finalize', 'getClass', 'getPresentationName', 'getRedoPresentationName', 'getUndoPresentationName', 'hashCode', 'inProgress', 'isInProgress', 'isSignificant', 'lastEdit', 'notify', 'notifyAll', 'presentationName', 'redo', 'redoPresentationName', 'replaceEdit', 'significant', 'toString', 'undo', 'undoPresentationName', 'wait']

And this is an extract of the CompoundEdit.java code:

public class CompoundEdit extends AbstractUndoableEdit {
    /**
     * True if this edit has never received <code>end.
     */
    boolean inProgress;

    /**
     * The collection of <code>UndoableEdits
     * undone/redone en masse by this <code>CompoundEdit.
     */
    protected Vector<UndoableEdit> edits;

    public CompoundEdit() {
        super();
        inProgress = true;
        edits = new Vector<UndoableEdit>();
    }

I have tried the exact same from Java, and it lets me access edits. Is there something I'm doing wrong in the Jython version? Is there a special way in Jython to access protected variables? In the documentation it mentions something about calling super__<method>(), but I tried it for this case and it also doesn't work.

1
  • Have you tried to set python.security.respectJavaAccessibility = false? See jython.org/jythonbook/en/1.0/… Commented Oct 17, 2018 at 11:43

1 Answer 1

1

@mzjn is correct. Setting python.security.respectJavaAccessibility = false is the only way to access a protected field from a subclass. This is due to this piece of code in org.python.core.PyJavaType.init(Class<?>, Set<PyJavaType>):

// Add fields declared on this type
Field[] fields;
if (Options.respectJavaAccessibility) {
    // returns just the public fields
    fields = forClass.getFields();
} else {
    fields = forClass.getDeclaredFields();
    for (Field field : fields) {
        field.setAccessible(true);
    }
}

However, you can call protected methods without setting respectJavaAccessibility to false, as method lookup uses a different algorithm. IMO this is a bug, I was not able to find any mentions that this behavior is intended.

Or just use Java reflection to get the protected field value:

class MyEdit(CompoundEdit):
    #...
    def get_edits(self):
        edits_field = CompoundEdit.getDeclaredField('edits')
        edits_field.setAccessible(True)
        return edits_field.get(self)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.