src.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 Show documentation
Show all versions of jython 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);
}
}