All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.org.python.core.PySuper Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 2.7.4
Show newest version
/* 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);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy