Skip to content

Commit dfd4cf5

Browse files
committed
Fixes #98 - first attempt at making things really work for python 3.8
1 parent b12b8ac commit dfd4cf5

8 files changed

Lines changed: 119 additions & 37 deletions

File tree

dockerfiles/CondaDockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ USER $USERNAME
3939
RUN conda create -n pyclj python=3.6 && conda install -n pyclj numpy mxnet \
4040
&& echo "source activate pyclj" > /home/$USERNAME/.bashrc
4141

42+
## cause leiningen to install
43+
RUN lein -v
44+
4245

4346
## To install pip packages into the pyclj environment do
4447
RUN conda run -n pyclj python3 -mpip install numpy

dockerfiles/Py38Dockerfile

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# We will use Ubuntu for our image
2+
FROM ubuntu:latest
3+
4+
# Updating Ubuntu packages
5+
6+
ARG CLOJURE_TOOLS_VERSION=1.10.1.507
7+
8+
9+
RUN apt-get -qq update && apt-get -qq -y install curl wget bzip2 openjdk-8-jdk-headless python3.8 libpython3.8 python3-pip \
10+
&& curl -o install-clojure https://download.clojure.org/install/linux-install-${CLOJURE_TOOLS_VERSION}.sh \
11+
&& chmod +x install-clojure \
12+
&& ./install-clojure && rm install-clojure \
13+
&& wget https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein \
14+
&& chmod a+x lein \
15+
&& mv lein /usr/bin \
16+
&& apt-get -qq -y autoremove \
17+
&& apt-get autoclean \
18+
&& rm -rf /var/lib/apt/lists/* /var/log/dpkg.log
19+
20+
21+
ARG USERID
22+
ARG GROUPID
23+
ARG USERNAME
24+
25+
RUN groupadd -g $GROUPID $USERNAME
26+
RUN useradd -u $USERID -g $GROUPID $USERNAME
27+
RUN mkdir /home/$USERNAME && chown $USERNAME:$USERNAME /home/$USERNAME
28+
USER $USERNAME
29+
30+
# Install leiningen during build process
31+
RUN lein -v
32+
RUN python3.8 -mpip install numpy

scripts/build-py38-docker

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
pushd dockerfiles
6+
docker build -t docker-py38 -f Py38Dockerfile --build-arg USERID=$(id -u) --build-arg GROUPID=$(id -u) --build-arg USERNAME=$USER .
7+
popd

scripts/py38-repl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
3+
lein update-in :dependencies conj \[nrepl\ \"0.6.0\"\]\
4+
-- update-in :plugins conj \[cider/cider-nrepl\ \"0.22.4\"\]\
5+
-- repl :headless :host localhost
6+

scripts/run-conda-docker

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ scripts/build-conda-docker
55
docker run --rm -it -u $(id -u):$(id -g) \
66
-v /$HOME/.m2:/home/$USER/.m2 \
77
-v $(pwd)/:/libpython-clj \
8-
-p 2222:2222 -w /libpython-clj \
8+
--net=host -w /libpython-clj \
99
docker-conda scripts/conda-repl

scripts/run-py38-docker

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
scripts/build-py38-docker
4+
5+
docker run --rm -it -u $(id -u):$(id -g) \
6+
-v /$HOME/.m2:/home/$USER/.m2 \
7+
-v $(pwd)/:/libpython-clj \
8+
--net=host -w /libpython-clj \
9+
docker-py38 scripts/py38-repl

src/libpython_clj/jna/base.clj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
(-> (Thread/currentThread)
7070
(.getId)))
7171

72-
(def gil-thread-id (AtomicLong. Long/MAX_VALUE))
72+
(defonce gil-thread-id (AtomicLong. Long/MAX_VALUE))
7373

7474

7575
(defn set-gil-thread-id!
@@ -106,7 +106,7 @@
106106
`(.invoke (jna-base/to-typed-fn ~'tvm-fn) ~'fn-args)))))
107107

108108

109-
(def size-t-type (type (jna/size-t 0)))
109+
(defonce size-t-type (type (jna/size-t 0)))
110110

111111

112112
(defn find-pylib-symbol

src/libpython_clj/python/interpreter.clj

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
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

Comments
 (0)