|
| 1 | +(ns libpython-clj2.metadata-test |
| 2 | + (:require [clojure.test :refer :all] |
| 3 | + [clojure.string :as str] |
| 4 | + [libpython-clj2.python :as py] |
| 5 | + [libpython-clj2.metadata :as metadata])) |
| 6 | + |
| 7 | +(deftest pyarglists-preserves-default-values |
| 8 | + (let [argspec {:args ["top" "topdown" "onerror"] |
| 9 | + :varargs nil |
| 10 | + :varkw nil |
| 11 | + :defaults ["." true nil] |
| 12 | + :kwonlyargs ["follow_symlinks" "dir_fd"] |
| 13 | + :kwonlydefaults (array-map "follow_symlinks" false |
| 14 | + "dir_fd" nil)}] |
| 15 | + (is (= '([& [{top "." |
| 16 | + topdown true |
| 17 | + onerror nil |
| 18 | + follow_symlinks false |
| 19 | + dir_fd nil}]] |
| 20 | + [& [{top "." |
| 21 | + topdown true |
| 22 | + follow_symlinks false |
| 23 | + dir_fd nil}]] |
| 24 | + [& [{top "." |
| 25 | + follow_symlinks false |
| 26 | + dir_fd nil}]] |
| 27 | + [& [{follow_symlinks false |
| 28 | + dir_fd nil}]]) |
| 29 | + (metadata/pyarglists argspec))))) |
| 30 | + |
| 31 | +(deftest py-fn-argspec-stringifies-python-object-defaults |
| 32 | + (let [testcode (py/import-module "testcode") |
| 33 | + default-type-fn (py/get-attr testcode "default_type_fn")] |
| 34 | + (is (= '([& [{dtype "<class 'int'>"}]] |
| 35 | + []) |
| 36 | + (-> default-type-fn |
| 37 | + metadata/py-fn-argspec |
| 38 | + metadata/pyarglists))))) |
| 39 | + |
| 40 | +(deftest py-fn-argspec-stringifies-kwonly-python-object-defaults |
| 41 | + (let [testcode (py/import-module "testcode") |
| 42 | + kw-default-type-fn (py/get-attr testcode "kw_default_type_fn")] |
| 43 | + (is (= '([& [{dtype "<class 'int'>"}]]) |
| 44 | + (-> kw-default-type-fn |
| 45 | + metadata/py-fn-argspec |
| 46 | + metadata/pyarglists))))) |
| 47 | + |
| 48 | +(defn- tc [n] (py/get-attr (py/import-module "testcode") n)) |
| 49 | + |
| 50 | +(defn- default-of [n sym] |
| 51 | + (->> (-> (tc n) metadata/py-fn-argspec metadata/pyarglists first) |
| 52 | + (tree-seq coll? seq) (filter map?) first sym)) |
| 53 | + |
| 54 | +(deftest py-default-class-object |
| 55 | + (is (= "<class 'int'>" (default-of "f_class" 'x)))) |
| 56 | + |
| 57 | +(deftest py-default-bad-repr-preserves-var |
| 58 | + (is (= '([& [{x "<unprintable>"}]] []) |
| 59 | + (-> (tc "f_badstr") metadata/py-fn-argspec metadata/pyarglists)))) |
| 60 | + |
| 61 | +(deftest py-default-custom-repr |
| 62 | + (is (= (apply str (repeat 40 "x")) (default-of "f_weird" 'x)))) |
| 63 | + |
| 64 | +(deftest py-default-partial |
| 65 | + (is (= "functools.partial(<class 'int'>, 0)" (default-of "f_partial" 'x)))) |
| 66 | + |
| 67 | +(deftest py-default-nested-opaque-no-pointer-leak |
| 68 | + (is (= "(<class 'int'>, <class 'str'>)" (default-of "f_nested_opaque" 'x)))) |
| 69 | + |
| 70 | +(deftest py-default-lambda |
| 71 | + (is (str/starts-with? (default-of "f_lambda" 'x) "<function <lambda> at 0x"))) |
| 72 | + |
| 73 | +(deftest py-default-sentinel |
| 74 | + (is (str/starts-with? (default-of "f_sentinel" 'x) "<object object at 0x"))) |
| 75 | + |
| 76 | +(deftest py-default-huge-truncated |
| 77 | + (let [s (default-of "f_huge" 'model)] |
| 78 | + (is (<= (count s) 203)) |
| 79 | + (is (str/ends-with? s "...")))) |
| 80 | + |
| 81 | +(deftest py-default-huge-kwonly-truncated |
| 82 | + (let [s (default-of "f_kw_huge" 'model)] |
| 83 | + (is (<= (count s) 203)) |
| 84 | + (is (str/ends-with? s "...")))) |
| 85 | + |
| 86 | +(deftest py-default-mixed |
| 87 | + (let [m (->> (-> (tc "f_mixed") metadata/py-fn-argspec metadata/pyarglists first) |
| 88 | + (tree-seq coll? seq) (filter map?) first)] |
| 89 | + (is (= 1 (m 'b))) |
| 90 | + (is (= "<class 'int'>" (m 'c))) |
| 91 | + (is (str/starts-with? (m 'd) "<object object at 0x")) |
| 92 | + (is (= 2 (m 'e))))) |
0 commit comments