src.org.python.modules._functools.PyPartial Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython-standalone Show documentation
Show all versions of jython-standalone 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.modules._functools;
import java.util.Map;
import org.python.core.Py;
import org.python.core.PyDictionary;
import org.python.core.PyNewWrapper;
import org.python.core.PyObject;
import org.python.core.PyStringMap;
import org.python.core.AbstractDict;
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.core.Traverseproc;
import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedSet;
import org.python.expose.ExposedType;
import org.python.util.Generic;
@ExposedType(name = "_functools.partial")
public class PyPartial extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyPartial.class);
/** The wrapped callable. */
@ExposedGet
public PyObject func;
/** Callable's args. */
public PyObject[] args;
/** Callable's keywords. */
private String[] keywords;
/** Lazily created dict for extra attributes. */
private PyObject __dict__;
public PyPartial() {
super(TYPE);
}
public PyPartial(PyType subType) {
super(subType);
}
@ExposedNew
public static PyObject partial___new__(PyNewWrapper new_, boolean init, PyType subtype,
PyObject[] args, String[] keywords) {
if (args.length - keywords.length < 1) {
throw Py.TypeError("type 'partial' takes at least one argument");
}
PyObject func = args[0];
if (!func.isCallable()) {
throw Py.TypeError("the first argument must be callable");
}
PyObject[] noFunc = new PyObject[args.length - 1];
System.arraycopy(args, 1, noFunc, 0, args.length - 1);
args = noFunc;
PyPartial partial;
if (new_.for_type == subtype) {
partial = new PyPartial();
} else {
partial = new PyPartialDerived(subtype);
}
partial.func = func;
partial.args = args;
partial.keywords = keywords;
return partial;
}
@Override
public PyObject __call__(PyObject[] args, String[] keywords) {
return partial___call__(args, keywords);
}
@ExposedMethod
public PyObject partial___call__(PyObject[] args, String[] keywords) {
PyObject[] argAppl;
String[] kwAppl;
int partialArgc = this.args.length - this.keywords.length;
int argc = args.length - keywords.length;
if (partialArgc == 0 && this.keywords.length == 0) {
argAppl = args;
kwAppl = keywords;
} else if (argc == 0 && keywords.length == 0) {
argAppl = this.args;
kwAppl = this.keywords;
} else {
// first merge keywords to determine the keyword count
Map merged = Generic.map();
int i;
for (i = 0; i < this.keywords.length; i++) {
String keyword = this.keywords[i];
PyObject value = this.args[partialArgc + i];
merged.put(keyword, value);
}
for (i = 0; i < keywords.length; i++) {
String keyword = keywords[i];
PyObject value = args[argc + i];
merged.put(keyword, value);
}
int keywordc = merged.size();
// finally merge into args and keywords arrays
argAppl = new PyObject[partialArgc + argc + keywordc];
System.arraycopy(this.args, 0, argAppl, 0, partialArgc);
System.arraycopy(args, 0, argAppl, partialArgc, argc);
kwAppl = new String[keywordc];
i = 0;
int j = partialArgc + argc;
for (Map.Entry entry : merged.entrySet()) {
kwAppl[i++] = entry.getKey();
argAppl[j++] = entry.getValue();
}
}
return func.__call__(argAppl, kwAppl);
}
@ExposedGet(name = "args")
public PyObject getArgs() {
PyObject[] justArgs;
if (keywords.length == 0) {
justArgs = args;
} else {
int argc = args.length - keywords.length;
justArgs = new PyObject[argc];
System.arraycopy(args, 0, justArgs, 0, argc);
}
return new PyTuple(justArgs);
}
@ExposedGet(name = "keywords")
public PyObject getKeywords() {
if (keywords.length == 0) {
return Py.None;
}
int argc = args.length - keywords.length;
PyObject kwDict = new PyDictionary();
for (int i = 0; i < keywords.length; i++) {
kwDict.__setitem__(Py.newString(keywords[i]), args[argc + i]);
}
return kwDict;
}
@Override
public void __setattr__(String name, PyObject value) {
partial___setattr__(name, value);
}
@ExposedMethod
final void partial___setattr__(String name, PyObject value) {
ensureDict();
super.__setattr__(name, value);
}
@Override
public PyObject fastGetDict() {
return __dict__;
}
@Override
@ExposedGet(name = "__dict__")
public PyObject getDict() {
ensureDict();
return __dict__;
}
@Override
@ExposedSet(name = "__dict__")
public void setDict(PyObject val) {
if (!(val instanceof AbstractDict)) {
throw Py.TypeError("setting partial object's dictionary to a non-dict");
}
__dict__ = val;
}
private void ensureDict() {
if (__dict__ == null) {
__dict__ = new PyStringMap();
}
}
/* Traverseproc implementation */
@Override
public int traverse(Visitproc visit, Object arg) {
int retVal;
if (func != null) {
retVal = visit.visit(func, arg);
if (retVal != 0) {
return retVal;
}
}
if (args != null) {
for (PyObject ob: args) {
if (ob != null) {
retVal = visit.visit(ob, arg);
if (retVal != 0) {
return retVal;
}
}
}
}
return __dict__ != null ? visit.visit(__dict__, arg) : 0;
}
@Override
public boolean refersDirectlyTo(PyObject ob) {
if (ob == null) {
return false;
}
if (args != null) {
for (PyObject obj: args) {
if (obj == ob) {
return true;
}
}
}
return ob == func || ob == __dict__;
}
}