From eb6cda30256356a59b35ab78467da30c613be0c9 Mon Sep 17 00:00:00 2001 From: Gerard Vermeulen Date: Sat, 24 Dec 2022 16:36:10 +0100 Subject: [PATCH] Switch to python-lsp-ruff and overhaul the Python and Eglot sections --- README.org | 354 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 246 insertions(+), 108 deletions(-) diff --git a/README.org b/README.org index 78e293a..4595186 100644 --- a/README.org +++ b/README.org @@ -3824,8 +3824,9 @@ Listing [[lst:configure-writegood-mode]] configures [[https://github.com/bnbeckw [[https://github.com/joaotavora/eglot#readme][Emacs polyGLOT (Eglot)]] is an Emacs language-server-protocol client that stays out of the way. The following listings contribute to a programming language mode independent [[https://github.com/joaotavora/eglot][Eglot]] configuration: -1. Listing [[lst:ensure-eglot-installation]] ensures installation of [[https://github.com/joaotavora/eglot][Eglot]] with - minimal configuration. +1. Listing [[lst:minimal-eglot-setup][minimal Eglot setup]] ensures installation of [[https://github.com/joaotavora/eglot][Eglot]], shows how to get + debug information from the [[https://github.com/python-lsp/python-lsp-server][Python LSP server]], and adds key bindings to + =eglot-mode-keymap=. 2. Listing [[lst:help-setup-org-src-mode-for-eglot]] and [[lst:setup-python-org-src-mode-for-eglot]] try to prepare any =org-src-mode= buffers for use with [[https://github.com/joaotavora/eglot][Eglot]]. They are a refactored implementation of the post @@ -3841,15 +3842,20 @@ mode independent [[https://github.com/joaotavora/eglot][Eglot]] configuration: file [[info:emacs#Directory Variables][.dir-locals.el]] in the root directory of any project using proper programming modes). -#+caption[Ensure =eglot= installation]: -#+caption: Ensure =eglot= installation. -#+name: lst:ensure-eglot-installation +#+caption[Ensure =eglot= installation with minimal configuration]: +#+caption: Ensure =eglot= installation with minimal configuration. +#+name: lst:minimal-eglot-setup #+begin_src emacs-lisp -(when (and (version< emacs-version "28.9.9") - (ensure-package-installation 'eglot)) - ;; (defvar eglot-server-programs - ;; `((python-mode . ("pylsp" "-vvv"))) - ;; "Shadow the definition of `eglot-server-programs' in `eglot'.") +(with-eval-after-load 'emacs + (when (version< emacs-version "28.9.9") + (ensure-package-installation 'eglot)) + + ;; Replace `nil' with `t' for debugging. + (when nil + (defvar eglot-server-programs + `((python-mode . ("pylsp" "-vvv"))) + "Shadow the definition of `eglot-server-programs' in `eglot'.")) + (with-eval-after-load 'eglot (define-key eglot-mode-map (kbd "C-c n") #'flymake-goto-next-error) (define-key eglot-mode-map (kbd "C-c p") #'flymake-goto-prev-error) @@ -4018,6 +4024,7 @@ Listing [[lst:configure-format-all]]: :PROPERTIES: :CUSTOM_ID: sec:flymake :END: + Flymake is an universal on-the-fly syntax checker for Emacs. It is a requirement of [[https://github.com/joaotavora/eglot][eglot]], but you can use it without [[https://github.com/joaotavora/eglot][eglot]] for instance in [[https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/progmodes/python.el][python-mode]] buffers that do not visit a file. @@ -4031,6 +4038,7 @@ that do not visit a file. :PROPERTIES: :CUSTOM_ID: sec:common-lisp-programming :END: + Listing [[lst:configure-sly]] configures the [[info:sly#Top][Sly (info)]] Common Lisp IDE for Emacs for use with [[http://www.sbcl.org/][Steel Bank Common Lisp (sbcl)]]: 1. It configures =sly-default-lisp= and =sly-lisp-implementations= as in the @@ -4302,45 +4310,62 @@ server, before plunging into the configuration steps: :CUSTOM_ID: sec:python-mode :END: -Listing [[lst:configure-python]] configures [[https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/progmodes/python.el][python-mode]] to use [[https://flake8.pycqa.org/en/latest/][flake8]] as style -checker and [[https://ipython.org/][IPython]] as shell interpreter and selects the Python interpreter by -means of src_emacs-lisp{(choose-common-python-interpreter)} defined in listing -[[lst:choose-common-python-interpreter]]. The [[https://github.com/pythonic-emacs/pythonic#readme][pythonic]] and [[https://github.com/jorgenschaefer/pyvenv#readme][pyvenv]] packages provide support -to handle Python virtual environments within Emacs. The [[https://github.com/pyenv/pyenv][pyenv]] package provides -support to work with [[https://github.com/pyenv/pyenv#readme][pyenv]] (eventually with [[https://github.com/pyenv/pyenv-virtualenv#readme][pyenv-virtualenv]]) to select between -different python versions (eventually each with different environments). In the -end, all those packages do is to set =python-shell-virtualenv-root= (in case of -[[https://github.com/pyenv/pyenv#readme][pyenv]] and [[https://github.com/pythonic-emacs/pythonic#readme][pythonic]]) and tweak the environment variables and restart the relevant -Python child processes (in case of [[https://github.com/jorgenschaefer/pyvenv#readme][pyvenv]]). Therefore, this setup replaces -those packages with listing [[lst:manage-pyenv]] to manage [[https://github.com/pyenv/pyenv#readme][pyenv]] from within Emacs -and listing [[lst:setting-python-shell-virtualenv-root]] to set -=python-shell-virtualenv-root=. +Listing [[lst:setup-python-mode][setup Python mode]] and [[lst:choose-common-python-interpreter][choose common Python interpreter]] select a common +Python interpreter in a virtual environment for use in =python-mode= and +=ob-python= by means of src_emacs-lisp{(choose-common-python-interpreter)}. The +[[https://github.com/pythonic-emacs/pythonic#readme][pythonic]], [[https://github.com/jorgenschaefer/pyvenv#readme][pyvenv]], and [[https://github.com/jorgenschaefer/pyvenv#readme][pyvenv]] packages allow to handle Python virtual +environments within Emacs. The [[https://github.com/pyenv/pyenv][pyenv]] package provides support to work with +[[https://github.com/pyenv/pyenv#readme][pyenv]] (eventually with [[https://github.com/pyenv/pyenv-virtualenv#readme][pyenv-virtualenv]]) to select between different python +versions (eventually each with different environments). In the end, all those +packages do is to set =python-shell-virtualenv-root= (in case of [[https://github.com/pyenv/pyenv#readme][pyenv]] and +[[https://github.com/pythonic-emacs/pythonic#readme][pythonic]]) or tweak the environment variables and restart the relevant Python +child processes (in case of [[https://github.com/jorgenschaefer/pyvenv#readme][pyvenv]]). Therefore, I replace those packages with +listing [[lst:access-pyenv][access pyenv]] and [[lst:select-python-virtual-environment][select a Python interpreter in a virtual environment]] to +set =python-shell-virtualenv-root= from within Emacs. -#+caption[Configure =python=]: -#+caption: Configure =python=. -#+name: lst:configure-python +Listing [[lst:setup-python-mode][setup Python mode]] and [[lst:choose-common-python-linter][choose common Python linter]] select a common Python +linter for the =python-check-command= and the =python-flymake-command= by means +of src_emacs-lisp{(choose-common-python-linter)} from: +1. [[https://github.com/PyCQA/pyflakes][Pyflakes - simple tool which checks Python source files for errors]]. +2. [[https://flake8.pycqa.org/en/latest/][Flake8 - your tool for style guide enforcement]]. +3. [[https://github.com/charliermarsh/ruff][Ruff - an extremely fast Python linter written in Rust]]. +I use [[https://pypi.org/project/ruff/][Ruff]] to replace [[https://pypi.org/project/flake8/][Flake8]] with a variety of its plugins. [[https://notes.crmarsh.com/][Charlie Marsh]] +explains why he started [[https://pypi.org/project/ruff/][Ruff]] in the post [[https://notes.crmarsh.com/python-tooling-could-be-much-much-faster][Python tooling could be much faster]]. + +Listing [[lst:pyproject-toml-kickoff][kickoff pyproject.toml proposal]] facilitates dropping a [[https://pip.pypa.io/en/stable/reference/build-system/pyproject-toml][pyproject.toml]] +file into Python projects which anyhow should switch to using a [[https://pip.pypa.io/en/stable/reference/build-system/pyproject-toml][pyproject.toml]] +file as explained in the post [[https://bbc.github.io/cloudfit-public-docs/packaging/this_way_up.html][This Way Up: A Bottom-Up Look At Python Packaging]]. + +Listing [[lst:setup-cfg-kickoff][kickoff setup.cfg proposal]] implements the [[https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html][using black with other tools]] +rules which 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]]. + +Finally, listing [[lst:flake8-nocolor][flake8-nocolor]] and [[lst:ruff-nocolor][ruff-nocolor]] pipe the =stdout= output of the +[[https://pypi.org/project/flake8/][flake8]] and [[https://pypi.org/project/ruff/][ruff]] executables through =cat= to remove escape sequences. + +#+caption[Setup Python mode]: +#+caption: Setup Python mode. +#+name: lst:setup-python-mode #+begin_src emacs-lisp (with-eval-after-load 'python (custom-set-variables - `(python-check-command ,(executable-find "flake8")) - `(python-flymake-command '(,(executable-find "flake8") "-")) '(python-indent-guess-indent-offset nil) '(python-shell-completion-native-disabled-interpreters '("ipython3" "pypy"))) - (choose-common-python-interpreter 'python)) + (choose-common-python-interpreter 'python) + (choose-common-python-linter 'ruff-nocolor)) #+end_src -#+caption[Choose common =python= interpreter for =ob-python= and =python-mode=]: -#+caption: Choose =python= interpreter for =ob-python= and =python-mode=. +#+caption[Choose a common Python interpreter]: +#+caption: Choose a common Python interpreter for =ob-python= and =python-mode=. #+name: lst:choose-common-python-interpreter #+begin_src emacs-lisp -(defun choose-common-python-interpreter (&optional program) - "Choose Python interpreter PROGRAM for `ob-python' and `python-mode'." +(defun choose-common-python-interpreter (&optional interpreter) + "Let `ob-python' and `python-mode' use the same Python INTERPRETER." (interactive) (let* ((prompt (format "Choose Python (%s): " (bound-and-true-p python-shell-interpreter))) (choices '(ipython python)) - (choice (if (member program choices) - (symbol-name program) + (choice (if (member interpreter choices) + (symbol-name interpreter) (completing-read prompt choices nil t)))) (when (boundp 'org-babel-python-command) (pcase choice @@ -4375,9 +4400,44 @@ and listing [[lst:setting-python-shell-virtualenv-root]] to set python-shell-interpreter)))) #+end_src -#+caption[Manage =pyenv=]: -#+caption: Manage =pyenv=. -#+name: lst:manage-pyenv +#+caption[Choose a common Python linter]: +#+caption: Choose a common Python linter for =python-check-command= and +#+caption: =python-flymake-command=. +#+name: lst:choose-common-python-linter +#+begin_src emacs-lisp +(defun choose-common-python-linter (&optional linter) + "Let `python-check-command' and `python-flymake-command' use the same LINTER." + (interactive) + (let* ((prompt (format "Choose Python checker (%s): " + (bound-and-true-p python-check-command))) + (choices '(flake8-nocolor pyflakes ruff-nocolor)) + (choice (if (member linter choices) + (symbol-name linter) + (completing-read prompt choices nil t)))) + (when (and (boundp 'python-check-command) (boundp 'python-flymake-command)) + (pcase choice + ("flake8-nocolor" + (custom-set-variables + `(python-check-command ,(executable-find choice)) + `(python-flymake-command (list ,(executable-find choice) "-")))) + ("pyflakes" + (custom-set-variables + `(python-check-command ,(executable-find choice)) + `(python-flymake-command `(,(executable-find choice))))) + ("ruff-nocolor" + (custom-set-variables + `(python-check-command ,(executable-find choice)) + `(python-flymake-command + (list ,(executable-find choice) "--stdin-filename" "stdin" "-"))))) + (when (bound-and-true-p python-check-custom-command) + (setq python-check-custom-command nil)) + (message "Python checker commands are %S and %S" + python-check-command python-flymake-command)))) +#+end_src + +#+caption[Access =pyenv=]: +#+caption: Access =pyenv=. +#+name: lst:access-pyenv #+begin_src emacs-lisp (when (executable-find "pyenv") (defun pyenv-full-path (version) @@ -4421,9 +4481,9 @@ Complete the result with \"system\"." (error "%s" (string-trim output)))))) #+end_src -#+caption[Setting =python-shell-virtualenv-root=]: -#+caption: Setting =python-shell-virtualenv-root=. -#+name: lst:setting-python-shell-virtualenv-root +#+caption[Select the Python virtual environment]: +#+caption: Select the Python virtual environment. +#+name: lst:select-python-virtual-environment #+begin_src emacs-lisp (with-eval-after-load 'python (when (cl-every #'fboundp '(pyenv-full-path @@ -4464,65 +4524,174 @@ Complete the result with \"system\"." python-shell-virtualenv-root))))) #+end_src +#+caption[Kickoff =pyproject.toml= proposal]: +#+caption: Kickoff =pyproject.toml= proposal. +#+name: lst:pyproject-toml-kickoff +#+begin_src toml :tangle pyproject.toml +# [project] +# name = "fancy-name" + +# [build-system] +# requires = ["setuptools", "wheel"] +# build-backend = "setuptools.build_meta" + +[tool.black] +line-length = 88 + +[tool.ruff] +line-length = 88 +select = [ + "ARG", # flake8-unused-arguments + "B", # flake8-bugbear + "C", # mccabe + "E", # pycodestyle + "D", # pydocstyle + "F", # pyflakes +# "W", # ruff emits no pycodestyle warnings yet +] + +ignore = [ + # https://www.pydocstyle.org/en/stable/error_codes.html#default-conventions + # pydocstyle numpy convention: + "D107", # ignore: missing docstring in __init__ + "D203", # ignore: single blank line required before class docstring + "D212", # ignore: multi-line docstring summary should start at the first line + "D213", # ignore: multi-line docstring summary should start at the second line + "D402", # ignore: first line should not be the function signature + "D413", # ignore: missing blank line after last section + "D415", # ignore: 1st line should end with a ".", "?", or "?" + "D416", # ignore: section name should end with a ":" + "D417", # ignore: missing argument descriptions in the docstring +] + +[tool.ruff.mccabe] +max-complexity = 15 + +# Local Variables: +# mode: conf-toml +# End: +#+end_src + +#+caption[Kickoff =setup.cfg= proposal]: +#+caption: Kickoff =setup.cfg= proposal. +#+name: lst:setup-cfg-kickoff +#+begin_src toml :tangle setup.cfg +[flake8] +docstring-convention = numpy +extend-select = B,F,W +extend-ignore = W503 +max-complexity = 15 +max-line-length = 88 + +[pycodestyle] +ignore = W503 +max-line-length = 88 + +# Local Variables: +# mode: conf-toml +# End: +#+end_src + +#+caption[Wrap =flake8= to remove color from text output]: +#+caption: Wrap =flake8= to remove color from text output. +#+header: :tangle-mode (identity #o755) +#+name: lst:flake8-nocolor +#+begin_src shell :noeval :tangle ~/bin/flake8-nocolor +#!/bin/sh + +flake8 "$@" | cat + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# sh-basic-offset: 2 +# End: +#+end_src + +#+caption[Wrap =ruff= to remove color from text output]: +#+caption: Wrap =ruff= to remove color from text output. +#+header: :tangle-mode (identity #o755) +#+name: lst:ruff-nocolor +#+begin_src shell :noeval :tangle ~/bin/ruff-nocolor +#!/bin/sh + +ruff "$@" | cat + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# sh-basic-offset: 2 +# End: +#+end_src + *** [[https://github.com/joaotavora/eglot][Eglot]] for [[https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/progmodes/python.el][python-mode]] :PROPERTIES: :CUSTOM_ID: sec:eglot-python :END: -Listing [[lst:configure-eglot+pylsp-with-pyls-flake8]] 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]] with the [[https://github.com/emanspeaks/pyls-flake8#readme][pyls-flake8]] plugin for the easiest way to -let [[https://github.com/python-lsp/python-lsp-server][python-lsp-server]] use [[https://github.com/PyCQA/flake8][flake8]]. 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-lsp/python-lsp-server][python-lsp-server]], [[https://github.com/python-rope/rope#readme][rope]], and [[https://github.com/google/yapf#readme][yapf]]. The -latest [[https://github.com/python-lsp/python-lsp-server#readme][python-lsp-server]] documentation tells to configure it for [[https://github.com/PyCQA/flake8][flake8]] as in -listing [[lst:configure-eglot+pylsp-sans-pyls-flake8]]. This method is under -investigation (it feels flaky since it shows some error messages twice). +Listing [[lst:configure-eglot+pylsp-ruff]] 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]] with the [[https://github.com/python-lsp/python-lsp-ruff#readme][pylsp-ruff]] plugin for the easiest way to let +[[https://github.com/python-lsp/python-lsp-server][python-lsp-server]] use [[https://pypi.org/project/ruff/][Ruff]]. The latest [[https://github.com/python-lsp/python-lsp-server#readme][python-lsp-server]] documentation tells to +configure it for [[https://github.com/PyCQA/flake8][flake8]] as in listing [[lst:configure-eglot+pylsp+flake8]]. 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-lsp/python-lsp-server][python-lsp-server]], [[https://github.com/python-rope/rope#readme][rope]], +and [[https://github.com/google/yapf#readme][yapf]]. This method is under investigation (it feels flaky since it shows +some error messages twice). + Listing [[lst:eglot-directory-variables-for-python]] shows a proper [[info:emacs#Directory Variables][.dir-locals.el]] file in the root directory of any [[https://www.python.org][Python]] project to start [[https://github.com/joaotavora/eglot][eglot]] automatically according to the configuration in listing [[lst:eglot-maybe-ensure]]. Type {{{kbd(M-x eglot-show-workspace-configuration)}}} to dump a =JSON= representation of src_emacs-lisp{eglot-workspace-configuration} for debugging. -The comment in listing [[lst:ensure-eglot-installation]] also shows how to increase -the the verbosity of [[https://github.com/python-lsp/python-lsp-server][python-lsp-server]] log output for debugging. +The comment in listing [[lst:minimal-eglot-setup][minimal Eglot setup]] also shows how to decrease +or to increase the verbosity of [[https://github.com/python-lsp/python-lsp-server][Python LSP server]] log output for debugging. -#+caption[Configure =eglot= with =python-lsp-server= with =pyls_flake8=]: -#+caption: Configure =eglot= with =python-lsp-server= with =pyls_flake8=. -#+name: lst:configure-eglot+pylsp-with-pyls-flake8 +#+caption[Configure =eglot= with =python-lsp-ruff=]: +#+caption: Configure =eglot= with =python-lsp-ruff=. +#+name: lst:configure-eglot+pylsp-ruff #+begin_src emacs-lisp (with-eval-after-load 'eglot (setq-default eglot-workspace-configuration - ;; Disable the `:pyls_flake8' plugin to fall back to pycodestyle. + ;; Enable the `:pyls_ruff' plugin and ensure to disable the + ;; `:flake8', `:mccabe', and `:pycodestye' plugins. '(:pylsp (:plugins - (:pyls_flake8 + (:pylsp_ruff (:enabled t) + :flake8 + (:enabled :json-false) + :mccabe + (:enabled :json-false) + :pycodestyle + (:enabled :json-false) :jedi (:auto_import_modules ["numpy"]) :jedi_completion (:cache_for ["astropy"])))))) #+end_src -#+caption[Configure =eglot= with =python-lsp-server= sans =pyls_flake8=]: -#+caption: Configure =eglot= with =python-lsp-server= sans =pyls_flake8=. -#+name: lst:configure-eglot+pylsp-sans-pyls-flake8 +#+caption[Configure =eglot= with =python-lsp-server= and the =flake8= plugin]: +#+caption: Configure =eglot= with =python-lsp-server= and the =flake8= plugin. +#+name: lst:configure-eglot+pylsp+flake8 #+begin_src emacs-lisp :tangle no (with-eval-after-load 'eglot (setq-default eglot-workspace-configuration - ;; How to use flake8 instead of pycodestyle officially, see: + ;; How to use flake8 instead of pycodestyle or ruff, see: ;; https://github.com/python-lsp/python-lsp-server#configuration '(:pylsp (:configurationSources ["flake8"] :plugins - (:pycodestyle - (:enabled :json-false) + (:flake8 + (:enabled t) :mccabe (:enabled :json-false) + :pycodestyle + (:enabled :json-false) :pyflakes - (:enabled - :json-false) - :flake8 - (:enabled t) + (:enabled :json-false) + :pylsp-ruff + (:enabled :json-false) :jedi (:auto_import_modules ["numpy"]) :jedi_completion @@ -4530,9 +4699,8 @@ the the verbosity of [[https://github.com/python-lsp/python-lsp-server][python-l #+end_src #+caption[A =.dir-locals.el= proposal to launch =eglot= automatically]: -#+caption: A =.dir-locals.el= proposal for any Python project -#+caption: or any Org-mode project tangling Python files -#+caption: to launch =eglot= automatically. +#+caption: A =.dir-locals.el= file proposal for Python projects or Org-mode +#+caption: projects tangling Python files to launch =eglot= automatically. #+name: lst:eglot-directory-variables-for-python #+begin_src emacs-lisp :tangle dir-locals.el ;; A .dir-locals.el file proposal in the root of any @@ -4540,10 +4708,17 @@ the the verbosity of [[https://github.com/python-lsp/python-lsp-server][python-l ;; to launch eglot automatically. ((nil ;; nil, since Emacs-29.1 filters out irrelevant variable names. . ((eglot-workspace-configuration - ;; Disable the `:pyls_flake8' plugin to fall back to pycodestyle. + ;; Enable the `:pyls_ruff' plugin and ensure to disable the + ;; `:flake8', `:mccabe', and `:pycodestye' plugins. . (:pylsp (:plugins - (:pyls_flake8 + (:pylsp_ruff (:enabled t) + :flake8 + (:enabled :json-false) + :mccabe + (:enabled :json-false) + :pycodestyle + (:enabled :json-false) :jedi (:auto_import_modules ["numpy"]) :jedi_completion @@ -4565,43 +4740,6 @@ the the verbosity of [[https://github.com/python-lsp/python-lsp-server][python-l | eldoc-doc-buffer | eglot-mode-map | {{{kbd(C-h .)}}} | |-------------------------+----------------+------------------| -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 - -# Local Variables: -# mode: conf-toml -# End: -#+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 - -# Local Variables: -# mode: conf-toml -# End: -#+end_src - Listing [[lst:make-pylsp-server-patch]] is useful to propagate eventual patches of a local fork of [[https://github.com/python-lsp/python-lsp-server][python-lsp-server]].