/* Copyright (c) Jython Developers */
package org.python.modules._weakref;
import org.python.core.ArgParser;
import org.python.core.Py;
import org.python.core.PyNewWrapper;
import org.python.core.PyObject;
import org.python.core.PyType;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@ExposedType(name = "weakref")
public class ReferenceType extends AbstractReference {
public static final PyType TYPE = PyType.fromClass(ReferenceType.class);
public ReferenceType(PyType subType, GlobalRef gref, PyObject callback) {
super(subType, gref, callback);
}
public ReferenceType(GlobalRef gref, PyObject callback) {
this(TYPE, gref, callback);
}
@ExposedNew
static final PyObject weakref___new__(PyNewWrapper new_, boolean init, PyType subtype,
PyObject[] args, String[] keywords) {
ArgParser ap = parseInitArgs("__new__", args, keywords);
PyObject ob = ap.getPyObject(0);
PyObject callback = ap.getPyObject(1, null);
if (callback == Py.None) {
callback = null;
}
GlobalRef gref = GlobalRef.newInstance(ob);
if (new_.for_type == subtype) {
// NOTE: CPython disallows weakrefs to many builtin types (e.g. dict, list)
// and would check weakrefability here. We aren't as strict since the JVM can
// weakref anything. Our types' needs_weakref flag only refers to whether it
// has a __weakref__ descriptor, not weakrefability
if (callback == null) {
ReferenceType ret = (ReferenceType)gref.find(ReferenceType.class);
if (ret != null) {
// We can re-use an existing reference.
return ret;
}
}
return new ReferenceType(gref, callback);
} else {
return new ReferenceTypeDerived(subtype, gref, callback);
}
}
@ExposedMethod
final void weakref___init__(PyObject[] args, String[] keywords) {
// Just ensure at least one arg, leaving other args alone
ArgParser ap = parseInitArgs("__init__", args, keywords);
ap.getPyObject(0);
}
/**
* Return an ArgParser setup to ignore keyword args (allowing them
* to passthru).
*
* @param funcName the name of the caller
* @param args PyObject array of args
* @param keywords String array of keywords
* @return an ArgParser instance
*/
private static ArgParser parseInitArgs(String funcName, PyObject[] args, String[] keywords) {
if (keywords.length > 0) {
int argc = args.length - keywords.length;
PyObject[] justArgs = new PyObject[argc];
System.arraycopy(args, 0, justArgs, 0, argc);
args = justArgs;
}
return new ArgParser(funcName, args, Py.NoKeywords, Py.NoKeywords);
}
public PyObject __call__(PyObject args[], String keywords[]) {
return weakref___call__(args, keywords);
}
@ExposedMethod
final PyObject weakref___call__(PyObject args[], String keywords[]) {
new ArgParser("__call__", args, keywords, Py.NoKeywords, 0);
return Py.java2py(gref.get());
}
public String toString() {
PyObject obj = (PyObject)gref.get();
if (obj == null) {
return String.format("<weakref at %s; dead>", Py.idstr(this));
}
PyObject nameObj = obj.__findattr__("__name__");
if (nameObj != null) {
return String.format("<weakref at %s; to '%.50s' at %s (%s)>", Py.idstr(this),
obj.getType().fastGetName(), Py.idstr(obj), nameObj);
}
return String.format("<weakref at %s; to '%.50s' at %s>", Py.idstr(this),
obj.getType().fastGetName(), Py.idstr(obj));
}
}