[Jython-checkins] jython: Add operator.methodcaller. Thanks Jezreel Ng!
frank.wierzbicki
jython-checkins at python.org
Fri Jun 22 21:53:05 CEST 2012
http://hg.python.org/jython/rev/136461d1ad22
changeset: 6735:136461d1ad22
user: Jezreel Ng <jezreel at gmail.com>
date: Fri Jun 22 12:52:17 2012 -0700
summary:
Add operator.methodcaller. Thanks Jezreel Ng!
files:
CPythonLib.includes | 2 +
CoreExposed.includes | 1 +
Lib/test/test_operator.py | 1 -
NEWS | 4 +-
src/org/python/modules/operator.java | 82 ++++++++++++++-
5 files changed, 79 insertions(+), 11 deletions(-)
diff --git a/CPythonLib.includes b/CPythonLib.includes
--- a/CPythonLib.includes
+++ b/CPythonLib.includes
@@ -115,6 +115,7 @@
pprint.py
profile.py
pstats.py
+pty.py
pyclbr.py
pydoc_topics.py
Queue.py
@@ -154,6 +155,7 @@
tokenize.py
trace.py
traceback.py
+tty.py
tzparse.py
urllib2.py
urlparse.py
diff --git a/CoreExposed.includes b/CoreExposed.includes
--- a/CoreExposed.includes
+++ b/CoreExposed.includes
@@ -92,6 +92,7 @@
org/python/modules/_weakref/ReferenceType.class
org/python/modules/operator$PyAttrGetter.class
org/python/modules/operator$PyItemGetter.class
+org/python/modules/operator$PyMethodCaller.class
org/python/modules/posix/PyStatResult.class
org/python/modules/random/PyRandom.class
org/python/modules/thread/PyLocal.class
diff --git a/Lib/test/test_operator.py b/Lib/test/test_operator.py
--- a/Lib/test/test_operator.py
+++ b/Lib/test/test_operator.py
@@ -447,7 +447,6 @@
self.assertEqual(operator.itemgetter(2,10,5)(data), ('2', '10', '5'))
self.assertRaises(TypeError, operator.itemgetter(2, 'x', 5), data)
- @unittest.skip("FIXME: broken")
def test_methodcaller(self):
self.assertRaises(TypeError, operator.methodcaller)
class A:
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -2,9 +2,11 @@
Jython 2.7a3
Bugs Fixed
+ - [ 1909 ] attrgetter does not parse dotted attributes
+ - [ 1924 ] Implement operator.methodcaller
- [ 1934 ] Break itertools.compress into a separate class
+ - [ 1933 ] Break itertools.cycle into a separate class
- [ 1932 ] Make check for iterability in chain() arguments lazy
- - [ 1933 ] Break itertools.cycle into a separate class
- [ 1931 ] Check that there are exactly 2 filter args
- [ 1913 ] Support short -W options
- [ 1897 ] 2.7.0ax only has partial ssl support
diff --git a/src/org/python/modules/operator.java b/src/org/python/modules/operator.java
--- a/src/org/python/modules/operator.java
+++ b/src/org/python/modules/operator.java
@@ -6,12 +6,14 @@
import org.python.core.Py;
import org.python.core.PyBuiltinFunctionSet;
import org.python.core.PyIgnoreMethodTag;
+import org.python.core.PyMethod;
import org.python.core.PyNewWrapper;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.core.PyUnicode;
+import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -243,6 +245,7 @@
dict.__setitem__("attrgetter", PyAttrGetter.TYPE);
dict.__setitem__("itemgetter", PyItemGetter.TYPE);
+ dict.__setitem__("methodcaller", PyMethodCaller.TYPE);
}
public static int countOf(PyObject seq, PyObject item) {
@@ -316,15 +319,7 @@
// XXX: We should probably have a PyObject.__getattr__(PyObject) that does
// this. This is different than __builtin__.getattr (in how it handles
// exceptions)
- String nameStr;
- if (name instanceof PyUnicode) {
- nameStr = ((PyUnicode)name).encode();
- } else if (name instanceof PyString) {
- nameStr = name.asString();
- } else {
- throw Py.TypeError(String.format("attribute name must be string, not '%.200s'",
- name.getType().fastGetName()));
- }
+ String nameStr = ensureStringAttribute(name);
String[] components = nameStr.split("\\.");
for (String component : components) {
obj = obj.__getattr__(component.intern());
@@ -379,4 +374,73 @@
return new PyTuple(result);
}
}
+
+ /**
+ * The methodcaller type.
+ */
+ @ExposedType(name = "operator.methodcaller", isBaseType = false)
+ static class PyMethodCaller extends PyObject {
+
+ public static final PyType TYPE = PyType.fromClass(PyMethodCaller.class);
+
+ public String name;
+ public PyObject[] args;
+ public String[] keywords;
+
+ @ExposedGet
+ public static PyString __doc__ = new PyString(
+ "methodcaller(name, ...) --> methodcaller object\n\n"
+ + "Return a callable object that calls the given method on its operand.\n"
+ + "After, f = methodcaller('name'), the call f(r) returns r.name().\n"
+ + "After, g = methodcaller('name', 'date', foo=1), the call g(r) returns\n"
+ + "r.name('date', foo=1)");
+
+ public PyMethodCaller(String name, PyObject[] args, String[] keywords) {
+ this.name = name;
+ this.args = args;
+ this.keywords = keywords;
+ }
+
+ @ExposedNew
+ final static PyObject methodcaller___new__(PyNewWrapper new_, boolean init,
+ PyType subtype, PyObject[] args,
+ String[] keywords) {
+
+ if (args.length == 0) {
+ throw Py.TypeError("methodcaller needs at least one argument, the method name");
+ }
+ String nameStr = ensureStringAttribute(args[0]);
+ PyObject[] newArgs = new PyObject[args.length-1];
+ System.arraycopy(args, 1, newArgs, 0, args.length-1);
+ return new PyMethodCaller(nameStr, newArgs, keywords);
+ }
+
+ @Override
+ public PyObject __call__(PyObject[] args, String[] keywords) {
+ return methodcaller___call__(args, keywords);
+ }
+
+ @ExposedMethod
+ final PyObject methodcaller___call__(PyObject[] args, String[] keywords) {
+ if (args.length > 1) {
+ throw Py.TypeError("methodcaller expected 1 arguments, got " + args.length);
+ }
+ ArgParser ap = new ArgParser("methodcaller", args, Py.NoKeywords, "obj");
+ PyObject obj = ap.getPyObject(0);
+ return obj.invoke(name, this.args, this.keywords);
+ }
+ }
+
+ private static String ensureStringAttribute(PyObject name) {
+ String nameStr;
+ if (name instanceof PyUnicode) {
+ nameStr = ((PyUnicode)name).encode();
+ } else if (name instanceof PyString) {
+ nameStr = name.asString();
+ } else {
+ throw Py.TypeError(String.format("attribute name must be string, not '%.200s'",
+ name.getType().fastGetName()));
+ }
+ return nameStr;
+ }
}
--
Repository URL: http://hg.python.org/jython
More information about the Jython-checkins
mailing list