Skip to content

Commit 52a7c2d

Browse files
committed
Parameterized *interp* to allow for initialization of interpreter.
1 parent bcbadd3 commit 52a7c2d

File tree

3 files changed

+84
-42
lines changed

3 files changed

+84
-42
lines changed

project.clj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
(defproject clojure-python "0.0.4"
22
:description "Improve seamlessness of Clojure Jython interop."
3-
:dependencies [[org.clojure/clojure "1.1.0"]
3+
:dependencies [[org.clojure/clojure "1.2.0"]
44
[org.python/jython "2.5.1"]]
55
:dev-dependencies [[lein-clojars "0.5.0"]
66
[swank-clojure "1.2.1"]]

src/clojure_python/core.clj

+73-41
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44
(org.python.core.*)))
55

66
;; instantiate a python interpreter in the python namespace
7-
(def *interp* (new org.python.util.PythonInterpreter))
7+
;(def *interp* (new org.python.util.PythonInterpreter))
88

99
(defn init
1010
"this may later take keywords and initialize other things
1111
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
1414
(.exec "import sys")
1515
(.exec (str "sys.path.append('" libpath "')"))))
16-
([libpath & more]
17-
(init libpath)
16+
([interp libpath & more]
17+
(init interp libpath)
1818
(apply init more)))
1919

2020
(defmacro py-import
@@ -23,32 +23,47 @@
2323
to be a library that has been imported,
2424
and the others are objects to import from this library"
2525
([] 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)
2931
__getitem__ ~(name lib))
3032
__dict__))
3133
(print ~lib)))
32-
([lib object] ; import object from a library
34+
([py lib object] ; import object from a library
3335
`(do (def ~object (.__finditem__
3436
~lib
3537
~(name object)))
3638
(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))))
4042

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))
4964

5065
(defmacro py-fn
51-
"create a native clojure function applying the python
66+
"create a native clojure function applying the python
5267
wrapper calls on a python function at the top level of the library
5368
use this where lambda is preferred over named function"
5469
[lib fun]
@@ -58,6 +73,40 @@
5873
(fn [& args#]
5974
(call f# args#))))
6075

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+
61110
(defmacro __
62111
"access attribute of class or attribute of attribute of (and so on) class"
63112
([class attr]
@@ -75,14 +124,17 @@
75124
non-keywords (filter (fn [a] (not (keyword? a))) args)]
76125
`(call (__ ~class ~@attrs) [~@non-keywords] ~@keywords))))
77126

127+
78128
(defn dir
79129
"it's slightly nicer to call the dir method in this way"
80130
[x] (seq (.__dir__ x)))
81131

132+
82133
(defn pyobj-nth
83134
"nth item in a 'PyObjectDerived'"
84135
[o i] (.__getitem__ o i))
85136

137+
86138
(defn pyobj-range
87139
"access 'PyObjectDerived' items as non-lazy range"
88140
[o start end] (for [i (range start end)] (pyobj-nth o i)))
@@ -91,24 +143,4 @@
91143
"access 'PyObjectDerived' items as Lazy Seq"
92144
[pyobj] (lazy-seq (.__iter__ pyobj)))
93145

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)))
104146

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))

test/clojure_python/core_test.clj

+10
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,13 @@
44

55
(deftest replace-me ;; FIXME: write
66
(is false "No tests have been written."))
7+
8+
(deftest test-python
9+
(let [py (python
10+
:pre-properties {:foo "bar"}
11+
:post-properties {:bar "foo"}
12+
:argv ["one" "two" "three"]
13+
:sys-path []
14+
:modules ['mod1 {:function ['f1 'f2] :objs ['o1 'o2]}])]))
15+
16+

0 commit comments

Comments
 (0)