Skip to content

Commit 4c18b30

Browse files
committed
Add an EQ_PROXY to PyJavaType to pass equals through to wrapped Java instances
like PyJavaInstance did. Make PyBuiltinMethod Cloneable and use clone to implement a default bind implementation. This eliminates 75% of the crud that came with creating a builtin method in Java.
1 parent 05bf180 commit 4c18b30

3 files changed

Lines changed: 72 additions & 176 deletions

File tree

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,30 @@
1-
// Copyright (c) Finn Bock
2-
31
package org.python.core;
42

5-
import java.util.Dictionary;
63
import java.util.Enumeration;
74
import java.util.Iterator;
8-
import java.util.Map;
9-
10-
class CollectionIter{
11-
PyObject findCollection(Object object) {
12-
if (object instanceof Map) {
13-
return new IteratorIter(((Map) object).keySet().iterator());
14-
}
15-
if (object instanceof Iterable) {
16-
return new IteratorIter(((Iterable)object).iterator());
17-
}
18-
if (object instanceof Iterator) {
19-
return new IteratorIter(((Iterator) object));
20-
}
21-
if (object instanceof Enumeration) {
22-
return new EnumerationIter(((Enumeration) object));
23-
}
24-
if (object instanceof Dictionary) {
25-
return new EnumerationIter(((Dictionary) object).keys());
26-
}
27-
28-
return null;
29-
}
30-
31-
}
325

336
class EnumerationIter extends PyIterator {
34-
private Enumeration proxy;
357

36-
public EnumerationIter(Enumeration proxy) {
8+
private Enumeration<Object> proxy;
9+
10+
public EnumerationIter(Enumeration<Object> proxy) {
3711
this.proxy = proxy;
3812
}
3913

4014
public PyObject __iternext__() {
41-
if (!this.proxy.hasMoreElements())
42-
return null;
43-
return Py.java2py(this.proxy.nextElement());
15+
return proxy.hasMoreElements() ? Py.java2py(proxy.nextElement()) : null;
4416
}
4517
}
4618

4719
class IteratorIter extends PyIterator {
48-
private Iterator proxy;
4920

50-
public IteratorIter(Iterator proxy) {
21+
private Iterator<Object> proxy;
22+
23+
public IteratorIter(Iterator<Object> proxy) {
5124
this.proxy = proxy;
5225
}
5326

5427
public PyObject __iternext__() {
55-
if (!this.proxy.hasNext())
56-
return null;
57-
return Py.java2py(this.proxy.next());
28+
return proxy.hasNext() ? Py.java2py(proxy.next()) : null;
5829
}
5930
}

src/org/python/core/PyBuiltinMethod.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
import org.python.expose.ExposeAsSuperclass;
44

5-
public abstract class PyBuiltinMethod extends PyBuiltinCallable implements ExposeAsSuperclass {
5+
public abstract class PyBuiltinMethod extends PyBuiltinCallable implements ExposeAsSuperclass,
6+
Cloneable {
67

78
protected PyObject self;
89

@@ -15,15 +16,31 @@ protected PyBuiltinMethod(PyObject self, Info info) {
1516
super(info);
1617
this.self = self;
1718
}
18-
19+
1920
protected PyBuiltinMethod(String name) {
2021
this(null, new DefaultInfo(name));
2122
}
22-
23+
24+
@Override
25+
public PyBuiltinCallable bind(PyObject bindTo) {
26+
if(self == null) {
27+
PyBuiltinMethod bindable;
28+
try {
29+
bindable = (PyBuiltinMethod)clone();
30+
} catch(CloneNotSupportedException e) {
31+
throw new RuntimeException("Didn't expect PyBuiltinMethodto throw " +
32+
"CloneNotSupported since it implements Cloneable", e);
33+
}
34+
bindable.self = bindTo;
35+
return bindable;
36+
}
37+
return this;
38+
}
39+
2340
public PyObject getSelf(){
2441
return self;
2542
}
26-
43+
2744
public PyMethodDescr makeDescriptor(PyType t) {
2845
return new PyMethodDescr(t, this);
2946
}

src/org/python/core/PyJavaType.java

Lines changed: 43 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,12 @@ protected void fillDict() {
4545
String methname = meth.getName();
4646
String nmethname = normalize_name(methname);
4747
PyReflectedFunction reflfunc = (PyReflectedFunction)dict.__finditem__(nmethname);
48-
boolean added = false;
4948
if (reflfunc == null) {
5049
dict.__setitem__(nmethname, new PyReflectedFunction(meth));
51-
added = true;
5250
} else {
5351
reflfunc.addMethod(meth);
54-
added = true;
5552
}
56-
if (added && !Modifier.isStatic(meth.getModifiers())) {
53+
if (!Modifier.isStatic(meth.getModifiers())) {
5754
// check for xxxX.*
5855
int n = meth.getParameterTypes().length;
5956
if (methname.startsWith("get") && n == 0) {
@@ -164,6 +161,7 @@ public PyObject new_impl(boolean init,
164161
}
165162
}
166163
}
164+
dict.__setitem__("__eq__", new PyMethodDescr(this, EQUALS_PROXY));
167165
if (ClassDictInit.class.isAssignableFrom(underlying_class)
168166
&& underlying_class != ClassDictInit.class) {
169167
try {
@@ -222,103 +220,42 @@ private static PyException error(Exception e) {
222220
return Py.JavaError(e);
223221
}
224222

225-
protected static class LenProxy extends PyBuiltinMethodNarrow {
226-
public LenProxy() {
227-
super("__len__", 0, 0);
228-
}
229-
230-
protected LenProxy(PyType type, PyObject self, Info info) {
231-
super(type, self, info);
232-
}
233-
234-
@Override
235-
public PyBuiltinCallable bind(PyObject self) {
236-
return new LenProxy(getType(), self, info);
237-
}
238-
223+
protected static final PyBuiltinMethodNarrow LEN_PROXY =
224+
new PyBuiltinMethodNarrow("__len__", 0, 0) {
239225
@Override
240226
public PyObject __call__() {
241227
return Py.newInteger(((Collection<?>)self.javaProxy).size());
242228
}
243-
}
244-
245-
protected static class MapGetProxy extends PyBuiltinMethodNarrow {
246-
public MapGetProxy() {
247-
super("__getitem__", 1, 1);
248-
}
249-
250-
protected MapGetProxy(PyType type, PyObject self, Info info) {
251-
super(type, self, info);
252-
}
253-
254-
@Override
255-
public PyBuiltinCallable bind(PyObject self) {
256-
return new MapGetProxy(getType(), self, info);
257-
}
229+
};
258230

231+
protected static final PyBuiltinMethodNarrow MAP_GET_PROXY =
232+
new PyBuiltinMethodNarrow("__getitem__", 1, 1) {
259233
@Override
260234
public PyObject __call__(PyObject key) {
261235
return Py.java2py(((Map<?, ?>)self.javaProxy).get(Py.tojava(key, Object.class)));
262236
}
263-
}
264-
265-
protected static class MapPutProxy extends PyBuiltinMethodNarrow {
266-
public MapPutProxy() {
267-
super("__setitem__", 2, 2);
268-
}
269-
270-
protected MapPutProxy(PyType type, PyObject self, Info info) {
271-
super(type, self, info);
272-
}
273-
274-
@Override
275-
public PyBuiltinCallable bind(PyObject self) {
276-
return new MapPutProxy(getType(), self, info);
277-
}
237+
};
278238

239+
protected static final PyBuiltinMethodNarrow MAP_PUT_PROXY =
240+
new PyBuiltinMethodNarrow("__setitem__", 2, 2) {
279241
@Override
280242
public PyObject __call__(PyObject key, PyObject value) {
281243
return Py.java2py(((Map<Object, Object>)self.javaProxy).put(Py.tojava(key, Object.class),
282244
Py.tojava(value,
283245
Object.class)));
284246
}
285-
}
286-
287-
protected static class MapRemoveProxy extends PyBuiltinMethodNarrow {
288-
289-
public MapRemoveProxy() {
290-
super("__delitem__", 1, 1);
291-
}
292-
293-
protected MapRemoveProxy(PyType type, PyObject self, Info info) {
294-
super(type, self, info);
295-
}
296-
297-
@Override
298-
public PyBuiltinCallable bind(PyObject self) {
299-
return new MapRemoveProxy(getType(), self, info);
300-
}
247+
};
301248

249+
protected static final PyBuiltinMethodNarrow MAP_REMOVE_PROXY =
250+
new PyBuiltinMethodNarrow("__delitem__", 1, 1) {
302251
@Override
303252
public PyObject __call__(PyObject key, PyObject value) {
304253
return Py.java2py(((Map<?, ?>)self.javaProxy).remove(Py.tojava(key, Object.class)));
305254
}
306-
}
307-
308-
protected static class ListGetProxy extends PyBuiltinMethodNarrow {
309-
public ListGetProxy() {
310-
super("__getitem__", 1, 1);
311-
}
312-
313-
protected ListGetProxy(PyType type, PyObject self, Info info) {
314-
super(type, self, info);
315-
}
316-
317-
@Override
318-
public PyBuiltinCallable bind(PyObject self) {
319-
return new ListGetProxy(getType(), self, info);
320-
}
255+
};
321256

257+
protected static final PyBuiltinMethodNarrow LIST_GET_PROXY =
258+
new PyBuiltinMethodNarrow("__getitem__", 1, 1){
322259
@Override
323260
public PyObject __call__(PyObject key) {
324261
if (key instanceof PyInteger) {
@@ -327,22 +264,10 @@ public PyObject __call__(PyObject key) {
327264
throw Py.TypeError("only integer keys accepted");
328265
}
329266
}
330-
}
331-
332-
protected static class ListSetProxy extends PyBuiltinMethodNarrow {
333-
public ListSetProxy() {
334-
super("__setitem__", 2, 2);
335-
}
336-
337-
protected ListSetProxy(PyType type, PyObject self, Info info) {
338-
super(type, self, info);
339-
}
340-
341-
@Override
342-
public PyBuiltinCallable bind(PyObject self) {
343-
return new ListSetProxy(getType(), self, info);
344-
}
267+
};
345268

269+
protected static final PyBuiltinMethodNarrow LIST_SET_PROXY =
270+
new PyBuiltinMethodNarrow("__setitem__", 2, 2) {
346271
@Override
347272
public PyObject __call__(PyObject key, PyObject value) {
348273
if (key instanceof PyInteger) {
@@ -353,62 +278,45 @@ public PyObject __call__(PyObject key, PyObject value) {
353278
}
354279
return Py.None;
355280
}
356-
}
357-
358-
protected static class ListRemoveProxy extends PyBuiltinMethodNarrow {
359-
public ListRemoveProxy() {
360-
super("__delitem__", 1, 1);
361-
}
362-
363-
protected ListRemoveProxy(PyType type, PyObject self, Info info) {
364-
super(type, self, info);
365-
}
281+
};
366282

367-
@Override
368-
public PyBuiltinCallable bind(PyObject self) {
369-
return new ListRemoveProxy(getType(), self, info);
370-
}
371-
372-
@Override
283+
protected static final PyBuiltinMethodNarrow LIST_REMOVE_PROXY =
284+
new PyBuiltinMethodNarrow("__delitem__", 1, 1) {
285+
@Override
373286
public PyObject __call__(PyObject key, PyObject value) {
374287
if (key instanceof PyInteger) {
375288
return Py.java2py(((List<Object>)self.javaProxy).remove(((PyInteger)key).getValue()));
376289
} else {
377290
throw Py.TypeError("only integer keys accepted");
378291
}
379292
}
380-
}
381-
382-
public static class IterableProxy extends PyBuiltinMethodNarrow {
383-
384-
public IterableProxy() {
385-
super("__iter__", 0, 0);
386-
}
293+
};
387294

388-
protected IterableProxy(PyType type, PyObject self, Info info) {
389-
super(type, self, info);
390-
}
391-
392-
@Override
393-
public PyBuiltinCallable bind(PyObject self) {
394-
return new IterableProxy(getType(), self, info);
295+
public static final PyBuiltinMethodNarrow ITERABLE_PROXY =
296+
new PyBuiltinMethodNarrow("__iter__", 0, 0) {
297+
public PyObject __call__() {
298+
return new IteratorIter(((Iterable)self.javaProxy).iterator());
395299
}
300+
};
396301

302+
public static final PyBuiltinMethodNarrow EQUALS_PROXY =
303+
new PyBuiltinMethodNarrow("__eq__", 1, 1) {
397304
@Override
398-
public PyObject __call__() {
399-
return new IteratorIter(((Iterable)self.javaProxy).iterator());
305+
public PyObject __call__(PyObject o) {
306+
return self.javaProxy.equals(o.__tojava__(self.javaProxy.getClass())) ? Py.True
307+
: Py.False;
400308
}
401-
}
309+
};
402310

403311
static Map<Class<?>, PyBuiltinMethod[]> _collectionProxies = Generic.map();
404312
static {
405-
_collectionProxies.put(Iterable.class, new PyBuiltinMethod[] {new IterableProxy()});
406-
_collectionProxies.put(Collection.class, new PyBuiltinMethod[] {new LenProxy()});
407-
_collectionProxies.put(Map.class, new PyBuiltinMethod[] {new MapGetProxy(),
408-
new MapPutProxy(),
409-
new MapRemoveProxy()});
410-
_collectionProxies.put(List.class, new PyBuiltinMethod[] {new ListGetProxy(),
411-
new ListSetProxy(),
412-
new ListRemoveProxy()});
313+
_collectionProxies.put(Iterable.class, new PyBuiltinMethod[] {ITERABLE_PROXY});
314+
_collectionProxies.put(Collection.class, new PyBuiltinMethod[] {LEN_PROXY});
315+
_collectionProxies.put(Map.class, new PyBuiltinMethod[] {MAP_GET_PROXY,
316+
MAP_PUT_PROXY,
317+
MAP_REMOVE_PROXY});
318+
_collectionProxies.put(List.class, new PyBuiltinMethod[] {LIST_GET_PROXY,
319+
LIST_SET_PROXY,
320+
LIST_REMOVE_PROXY});
413321
}
414322
}

0 commit comments

Comments
 (0)