Skip to content

Commit ad4f08c

Browse files
Handle conversion of generic-alias and union-type types in ->jvm (#251)
Co-authored-by: Mark Dawson <[email protected]>
1 parent 8ceda14 commit ad4f08c

File tree

2 files changed

+43
-27
lines changed

2 files changed

+43
-27
lines changed

Diff for: src/libpython_clj2/python/copy.clj

+34-27
Original file line numberDiff line numberDiff line change
@@ -172,36 +172,43 @@
172172
stop (py-base/->jvm (py-proto/get-attr pyobj "stop"))]
173173
(range start stop step))))
174174

175+
(def mapping-exceptions
176+
"These types pass PyMapping_Check but cannot be treated as a collection."
177+
;; See github issue#250
178+
#{:generic-alias
179+
:union-type})
175180

176181
(defmethod py-proto/pyobject->jvm :default
177182
[pyobj & [options]]
178-
(cond
179-
(= :none-type (py-ffi/pyobject-type-kwd pyobj))
180-
nil
181-
;;Things could implement mapping and sequence logically so mapping
182-
;;takes precedence
183-
(= 1 (py-ffi/PyMapping_Check pyobj))
184-
(do
185-
(if-let [map-items (py-ffi/PyMapping_Items pyobj)]
186-
(try
187-
(python->jvm-copy-hashmap pyobj map-items)
188-
(finally
189-
(py-ffi/Py_DecRef map-items)))
190-
(do
191-
;;Ignore error. The mapping check isn't thorough enough to work for all
192-
;;python objects.
193-
(py-ffi/PyErr_Clear)
194-
(python->jvm-copy-persistent-vector pyobj))))
195-
;;Sequences become persistent vectors
196-
(= 1 (py-ffi/PySequence_Check pyobj))
197-
(python->jvm-copy-persistent-vector pyobj)
198-
:else
199-
{:type (py-ffi/pyobject-type-kwd pyobj)
200-
;;Create a new GC root as the old reference is released.
201-
:value (let [new-obj (py-ffi/track-pyobject
202-
(Pointer. (.address (dt-ffi/->pointer pyobj))))]
203-
(py-ffi/Py_IncRef new-obj)
204-
new-obj)}))
183+
(let [python-type-keyword (py-ffi/pyobject-type-kwd pyobj)]
184+
(cond
185+
(= :none-type python-type-keyword)
186+
nil
187+
;;Things could implement mapping and sequence logically so mapping
188+
;;takes precedence
189+
(and (= 1 (py-ffi/PyMapping_Check pyobj))
190+
(not (mapping-exceptions python-type-keyword)))
191+
(do
192+
(if-let [map-items (py-ffi/PyMapping_Items pyobj)]
193+
(try
194+
(python->jvm-copy-hashmap pyobj map-items)
195+
(finally
196+
(py-ffi/Py_DecRef map-items)))
197+
(do
198+
;;Ignore error. The mapping check isn't thorough enough to work for all
199+
;;python objects.
200+
(py-ffi/PyErr_Clear)
201+
(python->jvm-copy-persistent-vector pyobj))))
202+
;;Sequences become persistent vectors
203+
(= 1 (py-ffi/PySequence_Check pyobj))
204+
(python->jvm-copy-persistent-vector pyobj)
205+
:else
206+
{:type python-type-keyword
207+
;;Create a new GC root as the old reference is released.
208+
:value (let [new-obj (py-ffi/track-pyobject
209+
(Pointer. (.address (dt-ffi/->pointer pyobj))))]
210+
(py-ffi/Py_IncRef new-obj)
211+
new-obj)})))
205212

206213

207214
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Diff for: test/libpython_clj2/require_python_test.clj

+9
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,12 @@
146146
"Methods have line numbers")
147147
(is (string? file)
148148
"Methods have file paths"))))
149+
150+
(deftest convert-types
151+
(let [typing-module (py/import-module "typing")]
152+
(testing "convert generic alias type to JVM"
153+
(-> (py/py. typing-module GenericAlias list str)
154+
py/->jvm
155+
:type
156+
(= :generic-alias)
157+
is))))

0 commit comments

Comments
 (0)