Skip to content

Commit 3d5d79b

Browse files
committed
Migrate to python-shell-with-environment.
Requires at least Emacs 25.
1 parent c59a158 commit 3d5d79b

File tree

1 file changed

+41
-184
lines changed

1 file changed

+41
-184
lines changed

pythonic.el

Lines changed: 41 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
;;; pythonic.el --- Utility functions for writing pythonic emacs package. -*- lexical-binding: t; -*-
22

3-
;; Copyright (C) 2015-2016 by Artem Malyshev
3+
;; Copyright (C) 2015-2018 by Artem Malyshev
44

55
;; Author: Artem Malyshev <proofit404@gmail.com>
66
;; URL: https://github.com/proofit404/pythonic
77
;; Version: 0.1.1
8-
;; Package-Requires: ((emacs "24") (cl-lib "0.5") (dash "2.11") (s "1.9") (f "0.17.2"))
8+
;; Package-Requires: ((emacs "25") (s "1.9") (f "0.17.2"))
99

1010
;; This program is free software; you can redistribute it and/or modify
1111
;; it under the terms of the GNU General Public License as published by
@@ -27,29 +27,19 @@
2727
;;; Code:
2828

2929
(require 'python)
30-
(require 'tramp)
31-
(require 'tramp-sh)
3230
(require 'cl-lib)
33-
(require 'dash)
31+
(require 'tramp)
3432
(require 's)
3533
(require 'f)
3634

37-
(defvaralias 'pythonic-environment
38-
(if (boundp 'python-shell-virtualenv-root)
39-
'python-shell-virtualenv-root
40-
'python-shell-virtualenv-path)
41-
"Alias to `python.el' virtualenv variable.")
42-
4335
(defun pythonic-remote-p ()
4436
"Determine remote or local virtual environment."
45-
(if pythonic-environment
46-
(tramp-tramp-file-p pythonic-environment)
47-
(tramp-tramp-file-p python-shell-interpreter)))
37+
(tramp-tramp-file-p default-directory))
4838

4939
(defun pythonic-remote-docker-p ()
5040
"Determine docker remote virtual environment."
5141
(and (pythonic-remote-p)
52-
(s-starts-with-p "/docker:" (pythonic-tramp-connection))))
42+
(s-starts-with-p "/docker:" (pythonic-remote-connection))))
5343

5444
(defun pythonic-remote-vagrant-p ()
5545
"Determine vagrant remote virtual environment."
@@ -59,168 +49,56 @@
5949

6050
(defun pythonic-remote-user ()
6151
"Get user of the connection to the remote python interpreter."
62-
(tramp-file-name-user
63-
(tramp-dissect-file-name
64-
(pythonic-tramp-connection))))
52+
(tramp-file-name-user (tramp-dissect-file-name (pythonic-remote-connection))))
6553

6654
(defun pythonic-remote-host ()
6755
"Get host of the connection to the remote python interpreter."
6856
(replace-regexp-in-string
6957
"#.*\\'" ""
70-
(tramp-file-name-host
71-
(tramp-dissect-file-name
72-
(pythonic-tramp-connection)))))
58+
(tramp-file-name-host (tramp-dissect-file-name (pythonic-remote-connection)))))
7359

7460
(defun pythonic-remote-port ()
7561
"Get port of the connection to the remote python interpreter."
76-
(let ((hostname (tramp-file-name-host
77-
(tramp-dissect-file-name
78-
(pythonic-tramp-connection)))))
62+
(let ((hostname (tramp-file-name-host (tramp-dissect-file-name (pythonic-remote-connection)))))
7963
(when (s-contains-p "#" hostname)
8064
(string-to-number (replace-regexp-in-string "\\`.*#" "" hostname)))))
8165

82-
(defun pythonic-file-name (file)
83-
"Normalized FILE location with out tramp prefix."
66+
(defun pythonic-local-file-name (file)
67+
"Local FILE name with out tramp prefix."
8468
(if (tramp-tramp-file-p file)
85-
(tramp-file-name-localname
86-
(tramp-dissect-file-name file))
69+
(tramp-file-name-localname (tramp-dissect-file-name file))
8770
file))
8871

89-
(defun pythonic-tramp-connection ()
90-
"Tramp connection string or nil."
91-
(-when-let* ((vars (--filter (tramp-tramp-file-p it)
92-
(list pythonic-environment
93-
python-shell-interpreter)))
94-
(var (car vars)))
95-
(substring var 0 (- (length var) (length (pythonic-file-name var))))))
96-
97-
(defun pythonic-executable ()
98-
"Python executable."
99-
(let* ((windowsp (eq system-type 'windows-nt))
100-
(python (if windowsp "pythonw" "python"))
101-
(bin (if windowsp "Scripts" "bin")))
102-
(if pythonic-environment
103-
(f-join (pythonic-file-name pythonic-environment) bin python)
104-
(pythonic-file-name python-shell-interpreter))))
72+
(defun pythonic-real-file-name (file)
73+
"Probably Remote FILE name with tramp prefix."
74+
(if (and (pythonic-remote-p)
75+
(not (tramp-tramp-file-p file)))
76+
(concat (pythonic-remote-connection) file)
77+
file))
10578

106-
(defun pythonic-default-directory (&optional from-directory)
79+
(defun pythonic-real-directory-name (directory)
10780
"Generate `default-directory' FROM-DIRECTORY."
108-
(let ((default-directory
109-
(concat (pythonic-tramp-connection)
110-
(or from-directory "~"))))
81+
(let ((default-directory (pythonic-real-file-name directory)))
11182
(f-full default-directory)))
11283

113-
(defun pythonic-set-process-environment ()
114-
"Set process environment variables from `python-mode' settings.
115-
It will use `python-shell-exec-path' for PATH variable,
116-
`python-shell-extra-pythonpaths' for PYTHONPATH variable."
117-
(if (pythonic-remote-p)
118-
(progn
119-
(pythonic-set-pythonpath-variable-tramp)
120-
(pythonic-set-path-variable-tramp)
121-
(pythonic-set-extra-variables-tramp))
122-
(pythonic-set-pythonpath-variable)
123-
(pythonic-set-path-variable)
124-
(pythonic-set-extra-variables)))
125-
126-
(defun pythonic-get-pythonpath ()
127-
"Get appropriate PYTHONPATH variable for pythonic process."
128-
(if (pythonic-remote-p)
129-
(pythonic-get-pythonpath-variable-tramp)
130-
(pythonic-get-pythonpath-variable)))
131-
132-
(defun pythonic-get-pythonpath-variable ()
133-
"Get PYTHONPATH variable from `python-shell-extra-pythonpaths' variable."
134-
(s-join path-separator
135-
(->> (or (getenv "PYTHONPATH") "")
136-
(s-split path-separator)
137-
(-union python-shell-extra-pythonpaths)
138-
(-remove 's-blank?)
139-
(-distinct))))
140-
141-
(defun pythonic-get-pythonpath-variable-tramp ()
142-
"Get PYTHONPATH variable form `python-shell-extra-pythonpaths' on the remote host."
143-
(let ((connection (tramp-dissect-file-name (pythonic-tramp-connection))))
144-
(s-join path-separator
145-
(--> (progn
146-
(tramp-send-command connection "echo $PYTHONPATH")
147-
(with-current-buffer (tramp-get-connection-buffer connection)
148-
(buffer-string)))
149-
(s-trim it)
150-
(s-split ":" it t)
151-
(--remove (member it python-shell-extra-pythonpaths) it)
152-
(append python-shell-extra-pythonpaths it)))))
153-
154-
(defun pythonic-set-pythonpath-variable ()
155-
"Set PYTHONPATH variable from `python-shell-extra-pythonpaths' variable."
156-
(setenv "PYTHONPATH" (pythonic-get-pythonpath-variable)))
157-
158-
(defun pythonic-set-pythonpath-variable-tramp ()
159-
"Set PYTHONPATH variable from `python-shell-extra-pythonpaths' variable on remote host."
160-
(tramp-send-command
161-
(tramp-dissect-file-name (pythonic-tramp-connection))
162-
(format
163-
"export PYTHONPATH=%s"
164-
(pythonic-get-pythonpath-variable-tramp))))
165-
166-
(defun pythonic-get-path ()
167-
"Return appropriate PATH variable for pythonic process."
168-
(if (pythonic-remote-p)
169-
(pythonic-get-path-variable-tramp)
170-
(pythonic-get-path-variable)))
171-
172-
(defun pythonic-get-path-variable ()
173-
"Get PATH variable according to `python-shell-exec-path'."
174-
(s-join path-separator
175-
(->> (or (getenv "PATH") "")
176-
(s-split path-separator)
177-
(-union python-shell-exec-path)
178-
(-remove 's-blank?)
179-
(-distinct))))
180-
181-
(defun pythonic-get-path-variable-tramp ()
182-
"Get PATH variable on remote host according to `python-shell-exec-path'."
183-
(let* ((vec (tramp-dissect-file-name (pythonic-tramp-connection)))
184-
(path (-distinct (append python-shell-exec-path (tramp-get-remote-path vec)))))
185-
(s-join path-separator path)))
186-
187-
(defun pythonic-set-path-variable ()
188-
"Set PATH according to `python-shell-exec-path'."
189-
(setenv "PATH" (pythonic-get-path-variable)))
190-
191-
(defun pythonic-set-path-variable-tramp ()
192-
"Set PATH according to `python-shell-exec-path' on remote host."
193-
(let* ((vec (tramp-dissect-file-name (pythonic-tramp-connection)))
194-
(path (s-split path-separator (pythonic-get-path-variable-tramp))))
195-
(tramp-set-connection-property vec "remote-path" path)
196-
(tramp-set-remote-path vec)))
197-
198-
(defun pythonic-set-extra-variables ()
199-
"Set environment variables according to `python-shell-process-environment'."
200-
(dolist (env python-shell-process-environment)
201-
(let ((env (s-split "=" env)))
202-
(setenv (car env) (cadr env)))))
203-
204-
(defun pythonic-set-extra-variables-tramp ()
205-
"Set remote environment variables from `python-shell-process-environment'."
206-
(dolist (env python-shell-process-environment)
207-
(tramp-send-command
208-
(tramp-dissect-file-name (pythonic-tramp-connection))
209-
(format "export %s" env))))
84+
(defun pythonic-remote-connection ()
85+
"Tramp connection string or nil."
86+
(when (pythonic-remote-p)
87+
(substring default-directory 0 (- (length default-directory)
88+
(length (pythonic-local-file-name default-directory))))))
21089

211-
(cl-defun call-pythonic (&key file buffer display args cwd)
90+
(cl-defun pythonic-call-process (&key file buffer display args cwd)
21291
"Pythonic wrapper around `call-process'.
21392
21493
FILE is the input file. BUFFER is the output destination. DISPLAY
21594
specifies to redisplay BUFFER on new output. ARGS is the list of
21695
arguments passed to `call-process'. CWD will be working directory
21796
for running process."
218-
(let ((default-directory (pythonic-default-directory cwd))
219-
(process-environment (copy-sequence process-environment)))
220-
(pythonic-set-process-environment)
221-
(apply 'process-file (pythonic-executable) file buffer display args)))
97+
(let ((default-directory (pythonic-real-directory-name (or cwd "~"))))
98+
(python-shell-with-environment
99+
(apply 'process-file python-shell-interpreter file buffer display args))))
222100

223-
(cl-defun start-pythonic (&key process buffer args cwd filter sentinel (query-on-exit t))
101+
(cl-defun pythonic-start-process (&key process buffer args cwd filter sentinel (query-on-exit t))
224102
"Pythonic wrapper around `start-process'.
225103
226104
PROCESS is a name of the created process. BUFFER is a output
@@ -230,49 +108,28 @@ process. FILTER must be a symbol of process filter function if
230108
necessary. SENTINEL must be a symbol of process sentinel
231109
function if necessary. QUERY-ON-EXIT will be corresponding
232110
process flag."
233-
(let ((default-directory (pythonic-default-directory cwd))
234-
(process-environment (copy-sequence process-environment))
235-
(buffer (and buffer (get-buffer-create buffer))))
236-
(pythonic-set-process-environment)
237-
(let ((process (apply 'start-file-process process buffer (pythonic-executable) args)))
238-
(when filter
239-
(set-process-filter process filter))
240-
(when sentinel
241-
(set-process-sentinel process sentinel))
242-
(set-process-query-on-exit-flag process query-on-exit)
243-
(process-put process
244-
'pythonic
245-
(list
246-
:executable (pythonic-executable)
247-
:connection (pythonic-tramp-connection)
248-
:pythonpath (pythonic-get-pythonpath)
249-
:path (pythonic-get-path)
250-
:environment python-shell-process-environment))
251-
process)))
252-
253-
(defun pythonic-proper-environment-p (process)
254-
"Determine if python environment has been changed since PROCESS was started."
255-
(--if-let (process-get process 'pythonic)
256-
(and
257-
(equal (plist-get it :executable) (pythonic-executable))
258-
(equal (plist-get it :connection) (pythonic-tramp-connection))
259-
(equal (plist-get it :pythonpath) (pythonic-get-pythonpath))
260-
(equal (plist-get it :path) (pythonic-get-path))
261-
(equal (plist-get it :environment) python-shell-process-environment))
262-
(error "Process %s wasn't started with `start-pythonic'"
263-
(process-name process))))
111+
(let ((default-directory (pythonic-real-directory-name (or cwd "~"))))
112+
(python-shell-with-environment
113+
(let ((process (apply 'start-file-process process buffer python-shell-interpreter args)))
114+
(when filter
115+
(set-process-filter process filter))
116+
(when sentinel
117+
(set-process-sentinel process sentinel))
118+
(set-process-query-on-exit-flag process query-on-exit)
119+
process))))
264120

265121
;;;###autoload
266122
(defun pythonic-activate (virtualenv)
267123
"Activate python VIRTUALENV."
268124
(interactive "DEnv: ")
269-
(setq pythonic-environment virtualenv))
125+
(setq python-shell-virtualenv-root
126+
(pythonic-local-file-name (pythonic-real-directory-name virtualenv))))
270127

271128
;;;###autoload
272129
(defun pythonic-deactivate ()
273130
"Deactivate python virtual environment."
274131
(interactive)
275-
(setq pythonic-environment nil))
132+
(setq python-shell-virtualenv-root nil))
276133

277134
(provide 'pythonic)
278135

0 commit comments

Comments
 (0)