Skip to content

Commit 52fbb72

Browse files
committed
Fixes #160
1 parent 75bae4c commit 52fbb72

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

src/libpython_clj2/python/bridge_as_jvm.clj

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
with the JVM -- Python dicts become java.util.Maps, for instance."
44
(:require [libpython-clj2.python.protocols :as py-proto]
55
[libpython-clj2.python.base :as py-base]
6+
[libpython-clj2.python.copy :as py-copy]
67
[libpython-clj2.python.fn :as py-fn]
78
[libpython-clj2.python.ffi :refer [with-gil] :as py-ffi]
89
[libpython-clj2.python.gc :as pygc]
10+
[tech.v3.datatype :as dtype]
11+
[tech.v3.datatype.protocols :as dt-proto]
912
[tech.v3.datatype.errors :as errors]
1013
[tech.v3.datatype.ffi :as dt-ffi]
1114
[clojure.core.protocols :as clj-proto])
12-
(:import [java.util Map]
15+
(:import [java.util Map Set]
1316
[clojure.lang IFn MapEntry Fn]
1417
[tech.v3.datatype.ffi Pointer]
1518
[tech.v3.datatype ObjectBuffer]))
@@ -197,7 +200,7 @@
197200
py-proto/PyCall
198201
(call [callable# arglist# kw-arg-map#]
199202
(with-gil
200-
(-> (py-fn/call-py-fn @pyobj*# arglist# kw-arg-map# py-base/->python)
203+
(-> (py-fn/call-py-fn @pyobj*# arglist# kw-arg-map# fn-arg->python)
201204
(py-base/as-jvm))))
202205
(marshal-return [callable# retval#]
203206
(with-gil
@@ -234,12 +237,33 @@
234237
(.write ^java.io.Writer w ^String (.toString ^Object pyobj)))
235238

236239

240+
(defn fn-arg->python
241+
"Slightly clever so we can pass ranges and such as function arguments."
242+
([item opts]
243+
(cond
244+
(dt-proto/convertible-to-range? item)
245+
(py-copy/->py-range item)
246+
(dtype/reader? item)
247+
(py-proto/->python (dtype/->reader item) opts)
248+
;;There is one more case here for iterables that aren't anything else -
249+
;; - specifically for sequences.
250+
(and (instance? Iterable item)
251+
(not (instance? Map item))
252+
(not (instance? String item))
253+
(not (instance? Set item)))
254+
(py-proto/as-python item opts)
255+
:else
256+
(py-base/->python item opts)))
257+
([item]
258+
(fn-arg->python item nil)))
259+
260+
237261
(defn call-impl-fn
238262
[fn-name att-map args]
239263
(if-let [py-fn* (get att-map fn-name)]
240264
;;laziness is carefully constructed here in order to allow the arguments to
241265
;;be released within the context of the function call during fn.clj call-py-fn.
242-
(-> (py-fn/call-py-fn @py-fn* args nil py-base/->python)
266+
(-> (py-fn/call-py-fn @py-fn* args nil fn-arg->python)
243267
(py-base/as-jvm))
244268
(throw (UnsupportedOperationException.
245269
(format "Python object has no attribute: %s"

src/libpython_clj2/python/copy.clj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,7 @@
326326
(py-proto/->python (dtype/->reader item) opts)
327327
;;There is one more case here for iterables (sequences)
328328
(instance? Iterable item)
329-
;;Iterables we *have* to convert lazily; we cannot copy them.
330-
(py-proto/as-python item opts)
329+
(py-proto/->python (vec item) opts)
331330
(instance? IFn item)
332331
(py-proto/as-python item opts)
333332
:else

test/libpython_clj2/python_test.clj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,11 @@ class Foo:
400400
(is (== 14 (np-dot np-ary np-ary)))))
401401

402402

403+
(deftest ->python-expands-sequences
404+
(let [test-dict {:a (seq [1 2 3 4 5 7 8 9])}
405+
py-dict (py/->python test-dict)
406+
py-data (py/get-item py-dict "a")]
407+
(is (= 8 (py/call-attr py-data "__len__")))))
403408

404409

405410
(comment

0 commit comments

Comments
 (0)