Revise the Python programming section

This commit is contained in:
Gerard Vermeulen 2022-01-07 16:34:21 +01:00
parent 42b8bedd4e
commit 42279d3036
3 changed files with 75 additions and 38 deletions

2
.gitignore vendored
View File

@ -12,11 +12,11 @@
*.lot *.lot
*.out *.out
*.pdf *.pdf
*.py
*.run.xml *.run.xml
*.tex *.tex
*.toc *.toc
example.py
latexmkrc latexmkrc
org-store-link org-store-link
setup-include.org setup-include.org

View File

@ -1695,31 +1695,52 @@ Listing [[lst:enable-pyenv-mode]] configures and enables =pyenv-mode=.
:CUSTOM_ID: sec:eglot :CUSTOM_ID: sec:eglot
:END: :END:
Listing [[lst:configure-eglot-for-python]] configures [[https://github.com/joaotavora/eglot][eglot]] with [[https://github.com/python-lsp/python-lsp-server][python-lsp-server]] Listing [[lst:configure-eglot+python-lsp-server-for-python]] (tangles to
for [[https://www.python.org][Python]]. It defines a hook function to launch [[https://github.com/joaotavora/eglot][eglot]] when it sees a proper =user-init-file=) and [[lst:configure-eglot+jedi-language-server-for-python]] (does
[[info:emacs#Directory not tangle to =user-init-file=) configure [[https://github.com/joaotavora/eglot][eglot]] for [[https://www.python.org][Python]] using either the
Variables][.dir-locals.el]] file in the root directory of any [[https://www.python.org][Python]] project. Listing [[https://github.com/python-lsp/python-lsp-server][python-lsp-server]] or experimentally the [[https://github.com/pappasam/jedi-language-server][jedi-language-server]]. Listing
[[lst:eglot-directory-variables-for-python]] shows such a proper [[info:emacs#Directory Variables][.dir-locals.el]] [[lst:on-hack-local-variables-hook-eglot-maybe]] defines a hook function to launch
file. [[https://github.com/joaotavora/eglot][eglot]] in presence of a proper [[info:emacs#Directory Variables][.dir-locals.el]] file in the root directory of any
[[https://www.python.org][Python]] project. Listing [[lst:eglot-directory-variables-for-python]] shows such a
proper [[info:emacs#Directory Variables][.dir-locals.el]] file.
#+caption[Configure =eglot= for Python]: #+caption[Configure =eglot= with =python-lsp-server= for Python]:
#+caption: Configure =eglot= for Python. #+caption: Configure =eglot= with =python-lsp-server= for Python.
#+name: lst:configure-eglot-for-python #+name: lst:configure-eglot+python-lsp-server-for-python
#+begin_src emacs-lisp #+begin_src emacs-lisp
(with-eval-after-load 'eglot (with-eval-after-load 'eglot
;; (setq eglot-server-programs '((python-mode "pylsp")))
(add-to-list 'eglot-server-programs '(python-mode "pylsp")) (add-to-list 'eglot-server-programs '(python-mode "pylsp"))
(setq-default (setq-default
eglot-workspace-configuration eglot-workspace-configuration
'((:pylsp . (:plugins (:jedi '((:pylsp . (:plugins (:jedi_completion (:cache_for ["astropy"]))))
(:auto_import_modules ["numpy" "scipy"])))) (:pylsp . (:plugins (:jedi (:auto_import_modules ["numpy"]))))
(:pylsp . (:plugins (:jedi_completion (:pylsp . (:configurationSources ["flake8"])))))
(:cache_for ["astropy"])))) #+end_src
(:pylsp . (:plugins (:jedi_completion (:eager t)))))))
#+caption[Configure =eglot= with =jedi-language-server= for Python]:
#+caption: Configure =eglot= with =jedi-langage-server= for Python.
#+name: lst:configure-eglot+jedi-language-server-for-python
#+begin_src emacs-lisp :tangle no
(with-eval-after-load 'eglot
;; (setq eglot-server-programs '((python-mode "jedi-language-server")))
(add-to-list 'eglot-server-programs '(python-mode "jedi-language-server"))
(setq-default
eglot-workspace-configuration
'((:jedi-language-server
. (:plugins (:jedi (:jediSettings (:autoImportModules ["numpy"]))))))))
#+end_src
#+caption[Start =eglot= in case of a proper =dir-local-variables-alist=]:
#+caption: Start =eglot= in case of a proper =dir-local-variables-alist=.
#+name: lst:on-hack-local-variables-hook-eglot-maybe
#+begin_src emacs-lisp
(when (fboundp 'eglot-ensure) (when (fboundp 'eglot-ensure)
;; The two hooks `after-change-major-mode-hook' and ;; The two hooks `after-change-major-mode-hook' and
;; `hack-local-variables-hook' are OK, but `<ANY>-mode-hook' is not. ;; `hack-local-variables-hook' are OK, but language mode hooks like
;; `python-mode-hook' are not.
(add-hook 'hack-local-variables-hook (add-hook 'hack-local-variables-hook
(defun on-hack-local-variables-hook-eglot-maybe () (defun on-hack-local-variables-hook-eglot-maybe ()
(when (and (derived-mode-p 'python-mode) (when (and (derived-mode-p 'python-mode)
@ -1736,17 +1757,24 @@ file.
;; Proposal for a .dir-locals.el file in the root of any Python project. ;; Proposal for a .dir-locals.el file in the root of any Python project.
((python-mode ((python-mode
. ((eglot-workspace-configuration . ((eglot-workspace-configuration
. ((:pylsp . (:plugins (:jedi . ((:pylsp . (:plugins (:jedi (:auto_import_modules ["numpy"]))))
(:auto_import_modules ["numpy" "scipy"])))) (:pylsp . (:plugins (:jedi_completion (:cache_for ["astropy"]))))
(:pylsp . (:plugins (:jedi_completion (:pylsp . (:configurationSources ["flake8"])))))))
(:cache_for ["astropy"]))))
(:pylsp . (:plugins (:jedi_completion (:eager nil)))))))))
#+end_src #+end_src
Here are a few links covering how to integrate Emacs, Python and a Python LSP
server:
1. [[https://taingram.org/blog/emacs-lsp-ide.html][Building Your Own Emacs IDE with LSP]]
2. [[https://rgoswami.me/posts/emacs-lang-servers/][Doom Emacs and Language Servers]]
3. [[https://ddavis.io/posts/eglot-python-ide/][Eglot based Emacs Python IDE]]
4. [[https://www.mattduck.com/lsp-python-getting-started.html][Getting started with lsp-mode for Python]]
5. [[https://ddavis.io/posts/python-emacs-3/][Python & Emacs, Take 3]]
6. [[https://ddavis.io/posts/emacs-python-lsp/][Python with Emacs: py(v)env and lsp-mode]]
[[https://jedi.readthedocs.io/en/latest/][Jedi]] provides grammar checking and completion candidates to [[https://github.com/python-lsp/python-lsp-server][python-lsp-server]]. [[https://jedi.readthedocs.io/en/latest/][Jedi]] provides grammar checking and completion candidates to [[https://github.com/python-lsp/python-lsp-server][python-lsp-server]].
Only [[https://jedi.readthedocs.io/en/latest/docs/changelog.html][jedi-0.18.1]] works with for instance [[https://numpy.org/][numpy-1.21.5]] in the sense that it Only [[https://jedi.readthedocs.io/en/latest/docs/changelog.html][jedi-0.18.1]] works with for instance [[https://numpy.org/][numpy-1.22.0]] in the sense that it
handles builtins and universal functions provided that [[https://jedi.readthedocs.io/en/latest/][jedi]] does not parse but handles builtins and universal functions provided that [[https://jedi.readthedocs.io/en/latest/][jedi]] does not parse but
imports [[https://numpy.org/][numpy-1.21.5]] (see [[https://github.com/davidhalter/jedi/issues/1744][jedi issue #1744]], [[https://github.com/davidhalter/jedi/issues/1745][#1745]], and [[https://github.com/davidhalter/jedi/issues/1746][#1746]]). imports [[https://numpy.org/][numpy-1.22.0]] (see [[https://github.com/davidhalter/jedi/issues/1744][jedi issue #1744]], [[https://github.com/davidhalter/jedi/issues/1745][#1745]], and [[https://github.com/davidhalter/jedi/issues/1746][#1746]]).
#+header: :wrap "src diff :exports code :tangle pylsp-auto-import-modules.patch" #+header: :wrap "src diff :exports code :tangle pylsp-auto-import-modules.patch"
#+begin_src shell :exports both :results org #+begin_src shell :exports both :results org
@ -1756,7 +1784,7 @@ imports [[https://numpy.org/][numpy-1.21.5]] (see [[https://github.com/davidhalt
#+RESULTS: #+RESULTS:
#+begin_src diff :exports code :tangle pylsp-auto-import-modules.patch #+begin_src diff :exports code :tangle pylsp-auto-import-modules.patch
diff --git a/pylsp/config/schema.json b/pylsp/config/schema.json diff --git a/pylsp/config/schema.json b/pylsp/config/schema.json
index c29d78b..f54b67a 100644 index c29d78b..4f30101 100644
--- a/pylsp/config/schema.json --- a/pylsp/config/schema.json
+++ b/pylsp/config/schema.json +++ b/pylsp/config/schema.json
@@ -69,6 +69,14 @@ @@ -69,6 +69,14 @@
@ -1765,7 +1793,7 @@ index c29d78b..f54b67a 100644
}, },
+ "pylsp.plugins.jedi.auto_import_modules": { + "pylsp.plugins.jedi.auto_import_modules": {
+ "type": "array", + "type": "array",
+ "default": ["numpy", "scipy", "gi"], + "default": ["numpy", "gi"],
+ "items": { + "items": {
+ "type": "string" + "type": "string"
+ }, + },
@ -1775,14 +1803,14 @@ index c29d78b..f54b67a 100644
"type": "array", "type": "array",
"default": [], "default": [],
diff --git a/pylsp/workspace.py b/pylsp/workspace.py diff --git a/pylsp/workspace.py b/pylsp/workspace.py
index bf312f6..49e967a 100644 index bf312f6..4758b53 100644
--- a/pylsp/workspace.py --- a/pylsp/workspace.py
+++ b/pylsp/workspace.py +++ b/pylsp/workspace.py
@@ -14,6 +14,8 @@ from . import lsp, uris, _utils @@ -14,6 +14,8 @@ from . import lsp, uris, _utils
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
+DEFAULT_AUTO_IMPORT_MODULES = ["numpy", "scipy", "gi"] +DEFAULT_AUTO_IMPORT_MODULES = ["numpy", "gi"]
+ +
# TODO: this is not the best e.g. we capture numbers # TODO: this is not the best e.g. we capture numbers
RE_START_WORD = re.compile('[A-Za-z_0-9]*$') RE_START_WORD = re.compile('[A-Za-z_0-9]*$')
@ -1803,13 +1831,16 @@ index bf312f6..49e967a 100644
:CUSTOM_ID: sec:anaconda :CUSTOM_ID: sec:anaconda
:END: :END:
Listing [[lst:configure-anaconda-for-python]] configures [[https://github.com/pythonic-emacs/anaconda-mode][anaconda]]. See Listing [[lst:configure-anaconda+company-for-python]] and
[[https://github.com/jorgenschaefer/elpy/blob/8d0de310d41ebf06b22321a8534546447456870c/elpy.el#L2775][elpy-module-company]] for how to handle ~company-backends~ as a local variable and [[lst:define-my-toggle-anaconda-mode]] configure [[https://github.com/pythonic-emacs/anaconda-mode][anaconda]]. See [[https://github.com/jorgenschaefer/elpy/blob/8d0de310d41ebf06b22321a8534546447456870c/elpy.el#L2775][elpy-module-company]]
the call to [[info:elisp#Advising Functions][advice-add]] opens Python org-mode edit-buffers in ~anaconda-mode~. for how to handle ~company-backends~ as a local variable in listing
[[lst:configure-anaconda+company-for-python]]. The call to [[info:elisp#Advising Functions][advice-add]] in listing
[[lst:define-my-toggle-anaconda-mode]] opens Python =org-edit-src-code= buffers in
~anaconda-mode~.
#+caption[Configure =anaconda= for Python]: #+caption[Configure =anaconda= with =company= for Python]:
#+caption: Configure =anaconda= for Python. #+caption: Configure =anaconda= with =company= for Python.
#+name: lst:configure-anaconda-for-python #+name: lst:configure-anaconda+company-for-python
#+begin_src emacs-lisp #+begin_src emacs-lisp
(with-eval-after-load 'python (with-eval-after-load 'python
(with-eval-after-load 'company (with-eval-after-load 'company
@ -1833,8 +1864,14 @@ the call to [[info:elisp#Advising Functions][advice-add]] opens Python org-mode
(delq 'company-capf (delq 'company-capf
(mapcar #'identity company-backends))))) (mapcar #'identity company-backends)))))
(anaconda-eldoc-mode (anaconda-eldoc-mode
(if (file-remote-p default-directory) -1 1)))))) (if (file-remote-p default-directory) -1 1)))))))
#+end_src
#+caption[Define =my-toggle-anaconda-mode= for Python]:
#+caption: Define =my-toggle-anaconda-mode= for Python.
#+name: lst:define-my-toggle-anaconda-mode
#+begin_src emacs-lisp
(with-eval-after-load 'python
(unless (and (fboundp 'my-disable-anaconda-mode) (unless (and (fboundp 'my-disable-anaconda-mode)
(fboundp 'my-enable-anaconda-mode)) (fboundp 'my-enable-anaconda-mode))
(when (fboundp 'anaconda-mode) (when (fboundp 'anaconda-mode)

View File

@ -1,5 +1,5 @@
diff --git a/pylsp/config/schema.json b/pylsp/config/schema.json diff --git a/pylsp/config/schema.json b/pylsp/config/schema.json
index c29d78b..f54b67a 100644 index c29d78b..4f30101 100644
--- a/pylsp/config/schema.json --- a/pylsp/config/schema.json
+++ b/pylsp/config/schema.json +++ b/pylsp/config/schema.json
@@ -69,6 +69,14 @@ @@ -69,6 +69,14 @@
@ -8,7 +8,7 @@ index c29d78b..f54b67a 100644
}, },
+ "pylsp.plugins.jedi.auto_import_modules": { + "pylsp.plugins.jedi.auto_import_modules": {
+ "type": "array", + "type": "array",
+ "default": ["numpy", "scipy", "gi"], + "default": ["numpy", "gi"],
+ "items": { + "items": {
+ "type": "string" + "type": "string"
+ }, + },
@ -18,14 +18,14 @@ index c29d78b..f54b67a 100644
"type": "array", "type": "array",
"default": [], "default": [],
diff --git a/pylsp/workspace.py b/pylsp/workspace.py diff --git a/pylsp/workspace.py b/pylsp/workspace.py
index bf312f6..49e967a 100644 index bf312f6..4758b53 100644
--- a/pylsp/workspace.py --- a/pylsp/workspace.py
+++ b/pylsp/workspace.py +++ b/pylsp/workspace.py
@@ -14,6 +14,8 @@ from . import lsp, uris, _utils @@ -14,6 +14,8 @@ from . import lsp, uris, _utils
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
+DEFAULT_AUTO_IMPORT_MODULES = ["numpy", "scipy", "gi"] +DEFAULT_AUTO_IMPORT_MODULES = ["numpy", "gi"]
+ +
# TODO: this is not the best e.g. we capture numbers # TODO: this is not the best e.g. we capture numbers
RE_START_WORD = re.compile('[A-Za-z_0-9]*$') RE_START_WORD = re.compile('[A-Za-z_0-9]*$')