// Copyright (c) Corporation for National Research Initiatives package org.python.core; /** * A python method. */ public class PyMethod extends PyObject { public PyObject im_self; public PyObject im_func; public PyObject im_class; public String __name__; public PyObject __doc__; public static PyClass __class__; public PyMethod(PyObject self, PyObject f, PyObject wherefound) { super(__class__); im_func = f; im_self = self; im_class = wherefound; } public PyMethod(PyObject self, PyFunction f, PyObject wherefound) { this(self, (PyObject)f, wherefound); __name__ = f.__name__; __doc__ = f.__doc__; } public PyMethod(PyObject self, PyReflectedFunction f, PyObject wherefound) { this(self, (PyObject)f, wherefound); __name__ = f.__name__; __doc__ = f.__doc__; } private static final String[] __members__ = { "im_self", "im_func", "im_class", "__doc__", "__name__", "__dict__", }; // TBD: this should be unnecessary public PyObject __dir__() { PyString members[] = new PyString[__members__.length]; for (int i = 0; i < __members__.length; i++) members[i] = new PyString(__members__[i]); PyList ret = new PyList(members); PyObject k = im_func.__getattr__("__dict__").invoke("keys"); ret.extend(k); return ret; } private void throwReadonly(String name) { for (int i = 0; i < __members__.length; i++) if (__members__[i] == name) throw Py.TypeError("readonly attribute"); throw Py.AttributeError(name); } public PyObject __findattr__(String name) { PyObject ret = super.__findattr__(name); if (ret != null) return ret; return im_func.__findattr__(name); } public void __delattr__(String name) { im_func.__delattr__(name); } public PyObject _doget(PyObject container) { return _doget(container, null); } public PyObject _doget(PyObject container, PyObject wherefound) { /* Only if classes are compatible */ if (container == null) return this; if (__builtin__.issubclass(container.__class__, (PyClass)im_class)) if (im_func instanceof PyFunction) return new PyMethod(container, (PyFunction)im_func, im_class); else if (im_func instanceof PyReflectedFunction) return new PyMethod(container, (PyReflectedFunction)im_func, im_class); else return new PyMethod(container, im_func, im_class); return this; } public PyObject __call__(PyObject[] args, String[] keywords) { if (im_self != null) // bound method return im_func.__call__(im_self, args, keywords); // unbound method. boolean badcall = false; if (im_class == null) // TBD: An example of this is running any function defined in // the os module. If you "import os", you'll find it's a // jclass object instead of a module object. Still unclear // whether that's wrong, but it's definitely not easily fixed // right now. Running, e.g. os.getcwd() creates an unbound // method with im_class == null. For backwards compatibility, // let this pass the call test ; else if (args.length < 1) badcall = true; else // first argument must be an instance who's class is im_class // or a subclass of im_class badcall = ! __builtin__.issubclass(args[0].__class__, (PyClass)im_class); if (badcall) { throw Py.TypeError("unbound method " + __name__ + "() must be " + "called with instance as first argument"); } else return im_func.__call__(args, keywords); } public int __cmp__(PyObject other) { if (other instanceof PyMethod) { PyMethod mother = (PyMethod)other; if (im_self != mother.im_self) return System.identityHashCode(im_self) < System.identityHashCode(mother.im_self) ? -1 : 1; if (im_func != mother.im_func) return System.identityHashCode(im_func) < System.identityHashCode(mother.im_func) ? -1 : 1; return 0; } return -2; } public String safeRepr() throws PyIgnoreMethodTag { return "'method' object"; } public String toString() { String classname = "?"; if (im_class != null && im_class instanceof PyClass) classname = ((PyClass)im_class).__name__; if (im_self == null) // this is an unbound method return ""; else return ""; } }