Revise Python section

* Generate Python project configuration files.
* Use pyls-flake8 again.
* Revise text.
This commit is contained in:
Gerard Vermeulen 2022-01-19 07:47:56 +01:00
parent 31379209f5
commit 194c97e69b
2 changed files with 72 additions and 51 deletions

2
.gitignore vendored
View File

@ -19,7 +19,9 @@
dir-locals.el
example.py
latexmkrc
pyproject.toml
org-store-link
setup.cfg
setup-include.org
tree.svg
worg-backend-dependent-execution-update.org

View File

@ -1058,8 +1058,8 @@ The code in listing [[lst:customize-org-babel]], [[lst:customize-org]], and
(cperl "perl")
(diff "diff")
(shell-script "bash")
(caml "ocaml")
(org "text")))
(org "text")
(toml "toml")))
'(org-latex-minted-options '(("bgcolor" "LightGoldenrodYellow")))
`(org-latex-logfiles-extensions
',(cl-union '("lof" "lot") org-latex-logfiles-extensions :test #'equal))
@ -1780,7 +1780,6 @@ non-interactive =org-element= functions to an =Emacs-lisp= buffer.
:PROPERTIES:
:CUSTOM_ID: sec:python-coding
:END:
The [[https://www.emacswiki.org/emacs/PythonProgrammingInEmacs][Python Programming in Emacs]] wiki page lists options to enhance Emacs's
built-in ~python-mode~. Here, the focus is on two packages:
1. [[https://github.com/joaotavora/eglot][Eglot - Emacs polyGLOT: an Emacs LSP client that stays out of your way]]. The
@ -1790,13 +1789,23 @@ built-in ~python-mode~. Here, the focus is on two packages:
shows.
2. [[https://github.com/pythonic-emacs/anaconda-mode][Anaconda - code navigation, documentation lookup, and completion for Python]].
In my opinion, [[https://github.com/joaotavora/eglot][eglot]] has more potential than [[https://github.com/pythonic-emacs/anaconda-mode][anaconda]], but [[https://github.com/pythonic-emacs/anaconda-mode][anaconda]] is
compatible with [[info:org#Editing Source Code][source code block editing]] while [[https://github.com/joaotavora/eglot][eglot]] is not. Listing
[[lst:configure-python]] configures [[https://www.python.org][Python]].
compatible with [[info:org#Editing Source Code][source code block editing]] while [[https://github.com/joaotavora/eglot][eglot]] is not.
Here are a few links covering how to integrate Emacs, Python and a Python LSP
server, before plunging into the configuring steps:
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://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/progmodes/python.el][Python-mode]]
:PROPERTIES:
:CUSTOM_ID: sec:python-mode
:END:
Listing [[lst:configure-python]] tells the Python shell to disregard its environment
variables (in particular =PYTHONSTARTUPFILE=).
#+caption[Configure =python=]:
#+caption: Configure =python=.
@ -1812,7 +1821,6 @@ compatible with [[info:org#Editing Source Code][source code block editing]] whil
:PROPERTIES:
:CUSTOM_ID: sec:pyenv
:END:
Listing [[lst:enable-pyenv-mode]] configures and enables =pyenv-mode=.
#+caption[Enable =pyenv-mode=]:
@ -1826,22 +1834,22 @@ Listing [[lst:enable-pyenv-mode]] configures and enables =pyenv-mode=.
;; Stop shadowing the org-mode-map "C-c C-s" binding.
(define-key pyenv-mode-map (kbd "C-c C-s") nil))
#+end_src
*** [[https://github.com/joaotavora/eglot][Eglot]]
:PROPERTIES:
:CUSTOM_ID: sec:eglot
:END:
Listing [[lst:configure-eglot+python-lsp-server-for-python]] tangles to
=user-init-file= and configures [[https://github.com/joaotavora/eglot][eglot]] for [[https://www.python.org][Python]] using the [[https://github.com/python-lsp/python-lsp-server][python-lsp-server]].
In order to enable all builtin [[https://github.com/python-lsp/python-lsp-server][python-lsp-server]] capabilities, ensure
installation of the Python packages [[https://github.com/hhatto/autopep8#readme][autopep8]], [[https://github.com/PyCQA/flake8][flake8]], [[https://github.com/PyCQA/pydocstyle#readme][pydocstyle]], [[https://github.com/PyCQA/pylint#readme][pylint]], [[https://github.com/python-rope/rope#readme][rope]],
and [[https://github.com/google/yapf#readme][yapf]]. In addition, install the [[https://github.com/emanspeaks/pyls-flake8#readme][pyls-flake8]] plugin to let [[https://github.com/python-lsp/python-lsp-server][python-lsp-server]]
use [[https://github.com/PyCQA/flake8][flake8]].
Listing [[lst:configure-eglot+python-lsp-server-for-python]] (tangles to
=user-init-file=) and [[lst:configure-eglot+jedi-language-server-for-python]] (does
not tangle to =user-init-file=) configure [[https://github.com/joaotavora/eglot][eglot]] for [[https://www.python.org][Python]] using the
[[https://github.com/python-lsp/python-lsp-server][python-lsp-server]] (or experimentally the less capable [[https://github.com/pappasam/jedi-language-server][jedi-language-server]]). In
order to enable all builtin [[https://github.com/python-lsp/python-lsp-server][python-lsp-server]] capabilities, ensure installation
of the Python packages [[https://github.com/hhatto/autopep8#readme][autopep8]], [[https://github.com/PyCQA/flake8][flake8]], [[https://github.com/PyCQA/pydocstyle#readme][pydocstyle]], [[https://github.com/PyCQA/pylint#readme][pylint]], [[https://github.com/python-rope/rope#readme][rope]], and
[[https://github.com/google/yapf#readme][yapf]]. Listing [[lst:on-hack-local-variables-hook-eglot-maybe]] defines a hook
function to launch [[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.
Listing [[lst:on-hack-local-variables-hook-eglot-maybe]] defines a hook function to
launch [[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= with =python-lsp-server= for Python]:
#+caption: Configure =eglot= with =python-lsp-server= for Python.
@ -1853,23 +1861,10 @@ file.
(setq-default
eglot-workspace-configuration
'((:pylsp . (:plugins (:jedi_completion (:cache_for ["astropy"]))))
(:pylsp . (:plugins (:jedi (:auto_import_modules ["numpy"]))))
(:pylsp . (:configurationSources ["flake8"])))))
#+end_src
#+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"]))))))))
'(;; Disable the `:pyls_flake8' plugin to fall back to pycodestyle.
(:pylsp . (:plugins (:pyls_flake8 (:enabled t))))
(:pylsp . (:plugins (:jedi_completion (:cache_for ["astropy"]))))
(:pylsp . (:plugins (:jedi (:auto_import_modules ["numpy"])))))))
#+end_src
#+caption[Start =eglot= in case of a proper =dir-local-variables-alist=]:
@ -1896,15 +1891,50 @@ file.
;; Proposal for a .dir-locals.el file in the root of any Python project.
((python-mode
. ((eglot-workspace-configuration
. ((:pylsp . (:plugins (:jedi (:auto_import_modules ["numpy"]))))
(:pylsp . (:plugins (:jedi_completion (:cache_for ["astropy"]))))
(:pylsp . (:configurationSources ["flake8"])))))))
. (;; Disable the `:pyls_flake8' plugin to fall back to pycodestyle.
(:pylsp . (:plugins (:pyls_flake8 (:enabled t))))
(:pylsp . (:plugins (:jedi (:auto_import_modules ["numpy"]))))
(:pylsp . (:plugins (:jedi_completion (:cache_for ["astropy"])))))))))
#+end_src
Allthough the configuration of [[https://github.com/pythonic-emacs/blacken#readme][blacken]] is not explicit, I use it to format all
new Python code with the [[https://black.readthedocs.io/en/stable/index.html][Python Black code formatter]]. Listing
[[lst:pyproject-toml-kick-off]] and [[lst:setup-cfg-kick-off]] implement the rules in
[[https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html][using black with other tools]] in order to make [[https://flake8.pycqa.org/en/latest/][flake8]] or [[https://pycodestyle.pycqa.org/en/latest/][pycodestyle]] agree with
[[https://black.readthedocs.io/en/stable/index.html][black's uncompromising style]].
#+caption[Kick starting a =pyproject.toml= file]:
#+caption: Kick starting a =pyproject.toml= file.
#+name: lst:pyproject-toml-kick-off
#+begin_src toml :tangle pyproject.toml
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
[tool.black]
line-length = 88
#+end_src
#+caption[Kick starting a =setup.cfg= file]:
#+caption: Kick starting a =setup.cfg= file.
#+name: lst:setup-cfg-kick-off
#+begin_src toml :tangle setup.cfg
[flake8]
max-line-length = 88
extend-ignore = E203
[pycodestyle]
ignore = E203
max-line-length = 88
#+end_src
[[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.22.0]] in the sense that it
handles universal functions provided that [[https://jedi.readthedocs.io/en/latest/][jedi]] does not parse but 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]]).
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 does
not choke on universal functions provided that [[https://jedi.readthedocs.io/en/latest/][jedi]] does not parse but 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]]). Since the universal
functions are neither builtin methods nor data instances but a kind of "callable
instances", the [[https://docs.python.org/3/library/inspect.html][Python inspect]] module also fails to handle the universal
functions properly.
Listing [[lst:make-pylsp-server-patch]] generates listing
[[lst:show-pylsp-server-patch]] that shows the patch to make [[https://jedi.readthedocs.io/en/latest/][jedi]] import
@ -1976,20 +2006,10 @@ index bf312f6..4758b53 100644
#+end_src
:end:
Finally, 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://github.com/pythonic-emacs/anaconda-mode][Anaconda]]
:PROPERTIES:
:CUSTOM_ID: sec:anaconda
:END:
Listing [[lst:configure-anaconda+company-for-python]] 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]]
for how to handle ~company-backends~ as a local variable in listing
@ -2060,7 +2080,6 @@ for how to handle ~company-backends~ as a local variable in listing
:PROPERTIES:
:CUSTOM_ID: sec:jedi
:END:
Listing [[lst:example-py]] is a [[https://www.python.org][Python]] example to test whether [[https://jedi.readthedocs.io/en/latest/][jedi]] in combination
with and either [[https://github.com/pythonic-emacs/anaconda-mode][anaconda]] or [[https://github.com/joaotavora/eglot][eglot]] works when coding certain functions of for
instance [[https://numpy.org/][numpy]] and [[https://scipy.org/][scipy]].