|
4 | 4 | (org.python.core.*)))
|
5 | 5 |
|
6 | 6 | ;; instantiate a python interpreter in the python namespace
|
7 |
| -(def *interp* (new org.python.util.PythonInterpreter)) |
| 7 | +;(def *interp* (new org.python.util.PythonInterpreter)) |
8 | 8 |
|
9 | 9 | (defn init
|
10 | 10 | "this may later take keywords and initialize other things
|
11 | 11 | for now it is just used to specify python library paths"
|
12 |
| - ([libpath] |
13 |
| - (doto clojure-python.core/*interp* |
| 12 | + ([interp libpath] |
| 13 | + (doto interp |
14 | 14 | (.exec "import sys")
|
15 | 15 | (.exec (str "sys.path.append('" libpath "')"))))
|
16 |
| - ([libpath & more] |
17 |
| - (init libpath) |
| 16 | + ([interp libpath & more] |
| 17 | + (init interp libpath) |
18 | 18 | (apply init more)))
|
19 | 19 |
|
20 | 20 | (defmacro py-import
|
|
23 | 23 | to be a library that has been imported,
|
24 | 24 | and the others are objects to import from this library"
|
25 | 25 | ([] nil)
|
26 |
| - ([lib] ; import a library |
27 |
| - `(do (. clojure-python.core/*interp* exec (str "import " ~(name lib))) |
28 |
| - (def ~lib (. (. (. clojure-python.core/*interp* getLocals) |
| 26 | + ([py] nil) |
| 27 | + ([py lib] ; import a library |
| 28 | + `(do |
| 29 | + (.exec ~py (str "import " ~(name lib))) |
| 30 | + (def ~lib (. (. (. ~py getLocals) |
29 | 31 | __getitem__ ~(name lib))
|
30 | 32 | __dict__))
|
31 | 33 | (print ~lib)))
|
32 |
| - ([lib object] ; import object from a library |
| 34 | + ([py lib object] ; import object from a library |
33 | 35 | `(do (def ~object (.__finditem__
|
34 | 36 | ~lib
|
35 | 37 | ~(name object)))
|
36 | 38 | (print ~object)))
|
37 |
| - ([lib object & more-objects] ; import multiple objects |
38 |
| - `(do (py-import ~lib ~object) |
39 |
| - (py-import ~lib ~@more-objects)))) |
| 39 | + ([py lib object & more-objects] ; import multiple objects |
| 40 | + `(do (py-import ~py ~lib ~object) |
| 41 | + (py-import ~py ~lib ~@more-objects)))) |
40 | 42 |
|
41 |
| -(defmacro import-fn |
42 |
| - "this is like import but it defines the imported item |
43 |
| - as a native function that applies the python wrapper calls" |
44 |
| - ([lib fun] |
45 |
| - `(def ~fun (py-fn ~lib ~fun))) |
46 |
| - ([lib fun & more-funs] |
47 |
| - `(do (import-fn ~lib ~fun) |
48 |
| - (import-fn ~lib ~@more-funs)))) |
| 43 | +(defn java2py |
| 44 | + "to wrap java objects for input as jython, and unwrap |
| 45 | + Jython output as java (thanks to Marc Downie on Clojure |
| 46 | + list for suggesting this)" |
| 47 | + [args] |
| 48 | + (into-array |
| 49 | + org.python.core.PyObject |
| 50 | + (map |
| 51 | + (fn [n] (. org.python.core.Py java2py n)) |
| 52 | + args))) |
| 53 | + |
| 54 | +(defn call |
| 55 | + "The first len(args)-len(keywords) members of args[] |
| 56 | + are plain arguments. The last len(keywords) arguments |
| 57 | + are the values of the keyword arguments." |
| 58 | + [fun args & key-args] |
| 59 | + (.__tojava__ |
| 60 | + (if key-args |
| 61 | + (.__call__ fun (java2py args) (into-array java.lang.String key-args)) |
| 62 | + (.__call__ fun (java2py args))) |
| 63 | + Object)) |
49 | 64 |
|
50 | 65 | (defmacro py-fn
|
51 |
| - "create a native clojure function applying the python |
| 66 | + "create a native clojure function applying the python |
52 | 67 | wrapper calls on a python function at the top level of the library
|
53 | 68 | use this where lambda is preferred over named function"
|
54 | 69 | [lib fun]
|
|
58 | 73 | (fn [& args#]
|
59 | 74 | (call f# args#))))
|
60 | 75 |
|
| 76 | +(defmacro import-fn |
| 77 | + "this is like import but it defines the imported item |
| 78 | + as a native function that applies the python wrapper calls" |
| 79 | + ([lib fun] |
| 80 | + `(def ~fun (py-fn ~lib ~fun))) |
| 81 | + ([lib fun & more-funs] |
| 82 | + `(do (import-fn ~lib ~fun) |
| 83 | + (import-fn ~lib ~@more-funs)))) |
| 84 | + |
| 85 | +(defn python-mod [py module [& {:keys [funcs objs]}]] |
| 86 | + (do |
| 87 | + (py-import py module) |
| 88 | + (if (seq objs) |
| 89 | + (dorun (map #(py-import py module %) objs))) |
| 90 | + (if (seq funcs) |
| 91 | + (dorun (map #(import-fn module %) funcs))))) |
| 92 | + |
| 93 | +(defn python [name [& {:keys |
| 94 | + [pre-properties |
| 95 | + post-properties |
| 96 | + argv |
| 97 | + sys-path |
| 98 | + modules]}]] |
| 99 | + (do |
| 100 | + (PythonInterpreter/initialize pre-properties post-properties argv) |
| 101 | + (let [interp (PythonInterpreter.)] |
| 102 | + (if (seq sys-path) |
| 103 | + (init interp sys-path)) |
| 104 | + (loop [mods modules] |
| 105 | + (let [[m args] (first modules) k (:funcs args) o (:objs args)] |
| 106 | + (python-mod interp m :funcs k :objs o) |
| 107 | + (recur (rest mods)))) |
| 108 | + interp))) |
| 109 | + |
61 | 110 | (defmacro __
|
62 | 111 | "access attribute of class or attribute of attribute of (and so on) class"
|
63 | 112 | ([class attr]
|
|
75 | 124 | non-keywords (filter (fn [a] (not (keyword? a))) args)]
|
76 | 125 | `(call (__ ~class ~@attrs) [~@non-keywords] ~@keywords))))
|
77 | 126 |
|
| 127 | + |
78 | 128 | (defn dir
|
79 | 129 | "it's slightly nicer to call the dir method in this way"
|
80 | 130 | [x] (seq (.__dir__ x)))
|
81 | 131 |
|
| 132 | + |
82 | 133 | (defn pyobj-nth
|
83 | 134 | "nth item in a 'PyObjectDerived'"
|
84 | 135 | [o i] (.__getitem__ o i))
|
85 | 136 |
|
| 137 | + |
86 | 138 | (defn pyobj-range
|
87 | 139 | "access 'PyObjectDerived' items as non-lazy range"
|
88 | 140 | [o start end] (for [i (range start end)] (pyobj-nth o i)))
|
|
91 | 143 | "access 'PyObjectDerived' items as Lazy Seq"
|
92 | 144 | [pyobj] (lazy-seq (.__iter__ pyobj)))
|
93 | 145 |
|
94 |
| -(defn java2py |
95 |
| - "to wrap java objects for input as jython, and unwrap |
96 |
| - Jython output as java (thanks to Marc Downie on Clojure |
97 |
| - list for suggesting this)" |
98 |
| - [args] |
99 |
| - (into-array |
100 |
| - org.python.core.PyObject |
101 |
| - (map |
102 |
| - (fn [n] (. org.python.core.Py java2py n)) |
103 |
| - args))) |
104 | 146 |
|
105 |
| -(defn call |
106 |
| - "The first len(args)-len(keywords) members of args[] |
107 |
| - are plain arguments. The last len(keywords) arguments |
108 |
| - are the values of the keyword arguments." |
109 |
| - [fun args & key-args] |
110 |
| - (.__tojava__ |
111 |
| - (if key-args |
112 |
| - (.__call__ fun (java2py args) (into-array java.lang.String key-args)) |
113 |
| - (.__call__ fun (java2py args))) |
114 |
| - Object)) |
|
0 commit comments