org.python.core.PySuper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython-slim Show documentation
Show all versions of jython-slim Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
/* Copyright (c) Jython Developers */
package org.python.core;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
/**
* The Python super type.
*/
@ExposedType(name = "super", doc = BuiltinDocs.super_doc)
public class PySuper extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PySuper.class);
@ExposedGet(name = "__thisclass__", doc = BuiltinDocs.super___thisclass___doc)
protected PyType superType;
@ExposedGet(name = "__self__", doc = BuiltinDocs.super___self___doc)
protected PyObject obj;
@ExposedGet(name = "__self_class__", doc = BuiltinDocs.super___self_class___doc)
protected PyType objType;
public PySuper() {
this(TYPE);
}
public PySuper(PyType subType) {
super(subType);
}
@ExposedMethod
@ExposedNew
public void super___init__(PyObject[] args, String[] keywords) {
if (keywords.length != 0 || !PyBuiltinCallable.DefaultInfo.check(args.length, 1, 2)) {
throw PyBuiltinCallable.DefaultInfo.unexpectedCall(args.length, keywords.length != 0,
"super", 1, 2);
}
if (!(args[0] instanceof PyType)) {
throw Py.TypeError("super: argument 1 must be type");
}
PyType type = (PyType)args[0];
PyObject obj = null;
PyType objType = null;
if (args.length == 2 && args[1] != Py.None) {
obj = args[1];
}
if (obj != null) {
objType = supercheck(type, obj);
}
this.superType = type;
this.obj = obj;
this.objType = objType;
}
/**
* Check that a super() call makes sense. Return a type object.
*
* obj can be a new-style class, or an instance of one:
*
* - If it is a class, it must be a subclass of 'type'. This case is used for class
* methods; the return value is obj.
*
* - If it is an instance, it must be an instance of 'type'. This is the normal case;
* the return value is obj.__class__.
*
* But... when obj is an instance, we want to allow for the case where objType is not
* a subclass of type, but obj.__class__ is! This will allow using super() with a
* proxy for obj.
*
* @param type the PyType superType associated with the super
* @param obj a the PyObject obj associated with the super
* @return a PyType superType
*/
private PyType supercheck(PyType type, PyObject obj) {
// Check for first bullet above (special case)
if (obj instanceof PyType && ((PyType)obj).isSubType(type)) {
return (PyType)obj;
}
// Normal case
PyType objType = obj.getType();
if (objType.isSubType(type)) {
return objType;
} else {
// Try the slow way
PyObject classAttr = obj.__findattr__("__class__");
if (classAttr != null && classAttr instanceof PyType) {
if (((PyType)classAttr).isSubType(type)) {
return (PyType)classAttr;
}
}
}
throw Py.TypeError("super(type, obj): obj must be an instance or subtype of type");
}
public PyObject __findattr_ex__(String name) {
return super___findattr_ex__(name);
}
final PyObject super___findattr_ex__(String name) {
if (objType != null && name != "__class__") {
PyObject descr = objType.super_lookup(superType, name);
if (descr != null) {
return descr.__get__(objType == obj ? null : obj, objType);
}
}
return super.__findattr_ex__(name);
}
@ExposedMethod(doc = BuiltinDocs.super___getattribute___doc)
final PyObject super___getattribute__(PyObject name) {
PyObject ret = super___findattr_ex__(asName(name));
if (ret == null) {
noAttributeError(asName(name));
}
return ret;
}
public PyObject __get__(PyObject obj, PyObject type) {
return super___get__(obj, type);
}
@ExposedMethod(defaults = "null", doc = BuiltinDocs.super___get___doc)
final PyObject super___get__(PyObject obj, PyObject type) {
if (obj == null || obj == Py.None || this.obj != null) {
return this;
}
if (getType() != TYPE) {
// If an instance of a (strict) subclass of super, call its type
return getType().__call__(type, obj);
} else {
// Inline the common case
PyType objType = supercheck(this.superType, obj);
PySuper newsuper = new PySuper();
newsuper.superType = this.superType;
newsuper.obj = obj;
newsuper.objType = objType;
return newsuper;
}
}
public String toString() {
String superTypeName = superType != null ? superType.fastGetName() : "NULL";
if (objType != null) {
return String.format(", <%s object>>", superTypeName,
objType.fastGetName());
} else {
return String.format(", NULL>", superTypeName);
}
}
public PyType getSuperType() {
return superType;
}
public PyObject getObj() {
return obj;
}
public PyType getObjType() {
return objType;
}
/* Traverseproc implementation */
@Override
public int traverse(Visitproc visit, Object arg) {
int retVal;
if (superType != null) {
retVal = visit.visit(superType, arg);
if (retVal != 0) {
return retVal;
}
}
if (obj != null) {
retVal = visit.visit(obj, arg);
if (retVal != 0) {
return retVal;
}
}
return objType == null ? 0 : visit.visit(objType, arg);
}
@Override
public boolean refersDirectlyTo(PyObject ob) {
return ob != null && (ob == superType || ob == obj || ob == objType);
}
}