99 [clojure.java.io :as io]
1010 [clojure.string :as s]
1111 [clojure.tools.logging :as log]
12- [clojure.data.json :as json])
12+ [clojure.data.json :as json]
13+ [clojure.pprint :as pp])
1314 (:import [libpython_clj.jna JVMBridge PyObject DirectMapped]
1415 [java.util.concurrent.atomic AtomicLong]
1516 [com.sun.jna Pointer]
@@ -91,11 +92,12 @@ print(json.dumps(
9192 (condp (partial =) (keyword platform)
9293 ; ; TODO: not sure what the strings returned by
9394 ; ; ..: mac and windows are for sys.platform
94- :linux " libpython%s.%sm.so$"
95- :mac " libpython%s.%sm.dylib$"
95+ :linux " libpython%s.%sm? .so$"
96+ :mac " libpython%s.%sm? .dylib$"
9697 :win32 " python%s%s.dll$" )
9798 major minor))))
9899
100+
99101(defn python-library-paths
100102 " Returns vector of matching python libraries in order of:
101103 - virtual-env (library)
@@ -105,6 +107,7 @@ print(json.dumps(
105107 - installation prefix (executable)
106108 - default executable location"
107109 [system-info python-regex]
110+ (println system-info)
108111 (transduce
109112 (comp
110113 (map io/file)
@@ -128,7 +131,7 @@ print(json.dumps(
128131(comment
129132 ; ; library paths workflow
130133
131- (let [executable " python3.7 "
134+ (let [executable " python3.6 "
132135 system-info (python-system-info executable)
133136 pyregex (python-library-regex system-info)]
134137 (python-library-paths system-info pyregex)))
@@ -142,13 +145,28 @@ print(json.dumps(
142145 (catch Throwable e nil )))
143146
144147
148+ (def default-python-executables
149+ [" python3" " python3.6" " python3.7" " python3.8" " python3.9" " python" ])
150+
151+
145152(defn detect-startup-info
146153 [{:keys [library-path python-home python-executable]}]
147154 (log-info
148155 (str " Detecting startup-info for Python executable: "
149156 python-executable))
150- (let [executable (or python-executable " python3" )
151- system-info (python-system-info executable)
157+ (let [executable-seq (concat
158+ (when python-executable
159+ [python-executable])
160+ default-python-executables )
161+ system-info (->> executable-seq
162+ (map #(try (python-system-info %)
163+ (catch Throwable e
164+ nil )))
165+ (remove nil?)
166+ (first ))
167+ _ (when-not system-info
168+ (throw (Exception. (format " Python executable was not found. Tried: %s"
169+ (vec executable-seq)))))
152170 python-home (cond
153171 python-home
154172 python-home
@@ -165,12 +183,21 @@ print(json.dumps(
165183 libname (or library-path
166184 (when (seq lib-version)
167185 (str " python" lib-version " m" )))
186+ libnames (concat [libname]
187+ ; ;Make sure we try without the 'm' suffix
188+ (when lib-version
189+ [(str " python" lib-version)]))
168190 retval
169- {:python-home python-home
170- :lib-version lib-version
171- :libname libname
172- :java-library-path-addendum java-library-path-addendum}]
173- (log/infof " Startup info detected: %s" retval)
191+ (merge
192+ system-info
193+ {:python-home python-home
194+ :lib-version lib-version
195+ :libname libname
196+ :libnames libnames
197+ :java-library-path-addendum java-library-path-addendum})]
198+ (log/infof " Startup info detected:\n %s"
199+ (with-out-str
200+ (pp/pprint (dissoc retval :libname ))))
174201 retval))
175202
176203
@@ -185,7 +212,8 @@ print(json.dumps(
185212
186213; ; Main interpreter booted up during initialize!
187214; ; * in the right to indicate atom
188- (def main-interpreter* (atom nil ))
215+ (defonce main-interpreter* (atom nil ))
216+
189217(defn main-interpreter
190218 ^Interpreter []
191219 @main-interpreter* )
@@ -295,7 +323,6 @@ print(json.dumps(
295323 (.get ^AtomicLong libpy-base/gil-thread-id))
296324
297325
298-
299326(defn ensure-interpreter
300327 ^Interpreter []
301328 (let [retval (main-interpreter )]
@@ -355,7 +382,6 @@ print(json.dumps(
355382(defonce ^:dynamic *program-name* " " )
356383
357384
358-
359385(defn- find-python-lib-version
360386 []
361387 (let [{:keys [out err exit]} (ignore-shell-errors " python3" " --version" )]
@@ -407,24 +433,21 @@ print(json.dumps(
407433
408434(defn initialize!
409435 [& {:keys [program-name
410- library-path
411- python-executable]
436+ library-path]
412437 :as options}]
413438 (when-not (main-interpreter )
414439 (log-info (str " Executing python initialize with options:" options))
415- (let [{:keys [python-home libname java-library-path-addendum] :as startup-info}
440+ (let [{:keys [python-home libnames java-library-path-addendum
441+ executable] :as startup-info}
416442 (detect-startup-info options)
417- library-names (cond
418- library-path
419- [library-path]
420- libname
421- (concat
422- [libname]
423- (libpy-base/library-names ))
424- :else
425- (libpy-base/library-names ))]
443+ library-names (concat
444+ (when library-path
445+ [library-path])
446+ libnames
447+ (libpy-base/library-names ))]
426448 (reset! python-home-wide-ptr* nil )
427449 (reset! python-path-wide-ptr* nil )
450+ (log/infof " Trying python library names %s" (vec library-names))
428451 (when python-home
429452 (append-java-library-path! java-library-path-addendum)
430453 ; ;This can never be released if load-library succeeeds
@@ -438,17 +461,19 @@ print(json.dumps(
438461 @python-home-wide-ptr*
439462 @python-path-wide-ptr*)))
440463 (recur library-names)))
441- (setup-direct-mapping! ))
442- ; ;Set program name
443- (when-let [program-name (or program-name *program-name* " " )]
444- (pygc/with-stack-context
445- (libpy/PySys_SetArgv 0 (-> program-name
446- (jna/string->wide-ptr )))))
464+ (setup-direct-mapping! )
465+ ; ;Set program name
466+ (when-let [program-name (or program-name executable " " )]
467+ (pygc/with-stack-context
468+ (libpy/PySys_SetArgv 0 (-> program-name
469+ (jna/string->wide-ptr ) )))))
447470 (let [type-symbols (libpy/lookup-type-symbols )
448471 context (do
449- (libpy-base/set-gil-thread-id! Long/MAX_VALUE (libpy-base/current-thread-id ))
472+ (libpy-base/set-gil-thread-id!
473+ Long/MAX_VALUE (libpy-base/current-thread-id ))
450474 (let [retval (libpy/PyEval_SaveThread )]
451- (libpy-base/set-gil-thread-id! (libpy-base/current-thread-id ) Long/MAX_VALUE)
475+ (libpy-base/set-gil-thread-id!
476+ (libpy-base/current-thread-id ) Long/MAX_VALUE)
452477 retval))]
453478 (construct-main-interpreter! context type-symbols))))
454479
0 commit comments