Skip to content

Commit 211b81c

Browse files
committed
Adding nil test for ->jvm and as-jvm. maps use getordefault for ifn overload now, and example of bridge.
1 parent 72339c4 commit 211b81c

File tree

6 files changed

+62
-5
lines changed

6 files changed

+62
-5
lines changed

project.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(defproject cnuernber/libpython-clj "1.9"
1+
(defproject cnuernber/libpython-clj "1.10-SNAPSHOT"
22
:description "libpython bindings to the techascent ecosystem"
33
:url "http://github.com/cnuernber/libpython-clj"
44
:license {:name "EPL-2.0"

src/libpython_clj/python.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050

5151

5252
(export-symbols libpython-clj.python.interop
53-
libpython-clj-module-name)
53+
libpython-clj-module-name
54+
create-bridge-from-att-map)
5455

5556

5657
(export-symbols libpython-clj.python.bridge

src/libpython_clj/python/bridge.clj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@
292292
(defn- py-impl-call-raw
293293
[att-name att-map arglist]
294294
(if-let [py-fn (get att-map att-name)]
295-
(-> (py-proto/do-call-fn py-fn (map as-python arglist) nil))
295+
(py-proto/do-call-fn py-fn (map as-python arglist) nil)
296296
(throw (UnsupportedOperationException.
297297
(format "Python object has no attribute: %s"
298298
att-name)))))
@@ -371,7 +371,7 @@
371371
(MapEntry. k v))))))]
372372
(.iterator ^Iterable mapentry-seq)))
373373
IFn
374-
(invoke [this arg] (.get this arg))
374+
(invoke [this arg] (.getOrDefault this arg nil))
375375
(invoke [this k v] (.put this k v))
376376
(applyTo [this arglist]
377377
(let [arglist (vec arglist)]

src/libpython_clj/python/object.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@
9191
(defn ->jvm
9292
"Copy an object into the jvm (if it wasn't there already.)"
9393
[item & [options]]
94-
(py-proto/->jvm item options))
94+
(when item
95+
(py-proto/->jvm item options)))
9596

9697

9798
(def ^:dynamic *object-reference-logging* false)

test/libpython_clj/python_test.clj

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,54 @@
197197
(py/call-attr item "doit_noerr"))
198198
(is (= ["enter" "exit: None"]
199199
(py/->jvm fn-list))))))
200+
201+
202+
(deftest arrow-as-fns-with-nil
203+
(py/initialize!)
204+
(is (= nil (py/->jvm nil)))
205+
(is (= nil (py/as-jvm nil))))
206+
207+
208+
(deftest pydict-nil-get
209+
(py/initialize!)
210+
(let [dict (py/->python {:a 1 :b {:a 1 :b 2}})
211+
bridged (py/as-jvm dict)]
212+
(is (= nil (bridged nil)))))
213+
214+
215+
(deftest custom-clojure-item
216+
(let [att-map {"clojure_fn" (py/->python #(vector 1 2 3))}
217+
my-python-item (py/create-bridge-from-att-map
218+
;;First is the jvm object that this bridge stands for. If this
219+
;;gets garbage collected then the python side will be removed
220+
;;also.
221+
att-map
222+
;;second is the list of attributes. In this case, since this
223+
;;object isn't iterable or anything, this function will do.
224+
att-map
225+
)
226+
py-mod (py/import-module "testcode")]
227+
(is (= [1 2 3]
228+
(py/call-attr py-mod "calling_custom_clojure_fn" my-python-item)))
229+
230+
;;Now this case is harder. Let's say we have something that is iterable and we
231+
;;want this to be reflected in python. In that case we have to call 'as-python'
232+
;;on the iterator and that 'should' work.
233+
234+
(let [my-obj (reify
235+
Iterable
236+
(iterator [this] (.iterator [4 5 6])))
237+
;;Note that attributes themselves have to be python objects and wrapping
238+
;;this with as-python makes that function wrap whatever it returns in a
239+
;;bridging python object also.
240+
att-map {"__iter__" (py/as-python #(.iterator my-obj))}
241+
my-python-item (py/create-bridge-from-att-map
242+
my-obj
243+
;;second is the list of attributes. In this case, since this
244+
;;object isn't iterable or anything, this function will do.
245+
att-map
246+
)]
247+
(is (= [4 5 6]
248+
(vec my-obj)))
249+
(is (= [4 5 6]
250+
(vec (py/call-attr py-mod "for_iter" my-python-item)))))))

testcode/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ def for_iter(arg):
1818
for item in arg:
1919
retval.append(item)
2020
return retval
21+
22+
23+
def calling_custom_clojure_fn(arg):
24+
return arg.clojure_fn()

0 commit comments

Comments
 (0)