Skip to content

Instantly share code, notes, and snippets.

@doolio
Last active May 10, 2024 15:47
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save doolio/8c1768ebf33c483e6d26e5205896217f to your computer and use it in GitHub Desktop.
Save doolio/8c1768ebf33c483e6d26e5205896217f to your computer and use it in GitHub Desktop.
.dir-locals.el for use with the Emacs Eglot LSP client and python-lsp-server (pylsp) LSP server
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
;;; Commentary:
;; .dir-locals.el for use with the Emacs Eglot LSP client and
;; python-lsp-server (pylsp) LSP server v1.10.0.
;; Default values in accordance with
;; https://github.com/python-lsp/python-lsp-server/blob/v1.10.0/CONFIGURATION.md
;; (or commit 2a5a953). A value of null means we do not set a value and
;; therefore use the plugin's default value.
;; The recommended format for the `eglot-workspace-configuration' variable
;; value is a property list (plist for short):
;;
;; (:server plist…)
;;
;; Here :server identifies a particular language server and plist is the
;; corresponding keyword-value property list of one or more parameter
;; settings for that server, serialized by Eglot as a JSON object.
;; plist may be arbitrarily complex, generally containing other
;; keyword-value property sublists corresponding to JSON subobjects.
;; The JSON values are represented by Emacs Lisp values as follows:
;; JSON | Emacs Lisp
;; ------------------------------------------------
;; :true i.e. true | t
;; :false i.e. false | :json-false
;; :null i.e. null | nil
;; :[] i.e. [] the empty array | []*
;; :{} i.e. {} the empty object | eglot-{}**
;; * Lisp array elements should not be comma separated as they are in a
;; JSON array.
;; ** Must be evaluated via a backquote or `list'
;; e.g. `(:pylsp (:plugins (:jedi (:env_vars ,eglot-{})))) or
;; (list :pylsp (list :plugins (list :jedi (list :env_vars eglot-{}))))
;;; How to Use:
;; 1. Place this file in your project directory.
;; 2. Adjust settings as desired. Inline comments below indicate the
;; expected type, possible values if appropriate and default pylsp value
;; for each configuration setting.
;;; Code:
((python-mode
. ((eglot-workspace-configuration
. (:pylsp (:configurationSources ["pycodestyle"] ; string array: ["flake8"] or ["pycodestyle"] (default)
:plugins (;; Note autopep uses some pycodestyle settings further down to avoid redefining things namely aggressive, exclude, hangClosing, ignore, maxLineLength and select
:autopep8
(:enabled t) ; boolean: true (default) or false
:flake8
(:config nil ; string: null (default)
:enabled :json-false ; boolean: true or false (default)
:exclude [] ; string array: [] (default)
:executable "flake8" ; string: "flake8" (default)
:extendIgnore [] ; string array: [] (default)
:filename nil ; string: null (default)
:hangClosing nil ; boolean: true or false; null (default)
:ignore [] ; string array: [] (default)
:indentSize nil ; integer: null (default)
:maxComplexity nil ; integer: null (default)
:maxLineLength nil ; integer: null (default)
:perFileIgnores [] ; string array: [] (default) e.g. ["file_path.py:W305,W304"]
:select nil) ; string array: null (default)
:jedi
(:auto_import_modules ["numpy"] ; string array: ["numpy"] (default)
:env_vars nil ; object: null (default)
:environment nil ; string: null (default)
:extra_paths []) ; string array: [] (default)
:jedi_completion
(:cache_for ["pandas" "numpy" "tensorflow" "matplotlib"] ; string array: ["pandas", "numpy", "tensorflow", "matplotlib"] (default)
:eager :json-false ; boolean: true or false (default)
:enabled t ; boolean: true (default) or false
:fuzzy :json-false ; boolean: true or false (default)
:include_class_objects :json-false ; boolean: true or false (default)
:include_function_objects :json-false ; boolean: true or false (default)
:include_params t ; boolean: true (default) or false
:resolve_at_most 25) ; integer: 25 (default)
:jedi_definition
(:enabled t ; boolean: true (default) or false
:follow_builtin_definitions t ; boolean: true (default) or false
:follow_builtin_imports t ; boolean: true (default) or false
:follow_imports t) ; boolean: true (default) or false
:jedit_hover
(:enabled t) ; boolean: true (default) or false
:jedi_references
(:enabled t) ; boolean: true (default) or false
:jedi_signature_help
(:enabled t) ; boolean: true (default) or false
:jedi_symbols
(:all_scopes t ; boolean: true (default) or false
:enabled t ; boolean: true (default) or false
:include_import_symbols t) ; boolean: true (default) or false
:mccabe
(:enabled t ; boolean: true (default) or false
:threshold 15) ; integer: 15 (default)
:preload
(:enabled t ; boolean: true (default) or false
:modules []) ; string array: [] (default)
:pycodestyle
(:enabled t ; boolean: true (default) or false
:exclude [] ; string array: [] (default)
:filename [] ; string array: [] (default)
:hangClosing nil ; boolean: true or false; null (default)
:ignore [] ; string array: [] (default)
:indentSize nil ; integer: null (default)
:maxLineLength nil ; integer: null (default)
:select nil) ; string array: null (default)
:pydocstyle
(:addIgnore [] ; string array: [] (default)
:addSelect [] ; string array: [] (default)
:convention nil ; string: "google", "numpy" or "pep257"; null (default)
:enabled :json-false ; boolean: true or false (default)
:ignore [] ; string array: [] (default)
:match "(?!test_).*\\.py" ; string: "(?!test_).*\\.py" (default)
:matchDir "[^\\.].*" ; string: "[^\\.].*" (default)
:select nil) ; string array: null (default)
:pyflakes
(:enabled t) ; boolean: true (default) or false
:pylint
(:args [] ; string array: [] (default)
:enabled :json-false ; boolean: true or false (default)
:executable nil) ; string: null (default)
:rope_autoimport
(:code_actions (:enabled t) ; boolean: true (default) or false
:completions (:enabled t) ; boolean: true (default) or false
:enabled :json-false ; boolean: true or false (default)
:memory :json-false) ; boolean: true or false (default)
:rope_completion
(:eager :json-false ; boolean: true or false (default)
:enabled :json-false) ; boolean: true or false (default)
:yapf
(:enabled t)) ; boolean: true (default) or false
:rope
(:extensionModules nil ; string: null (default)
:ropeFolder nil))))))) ; string array: null (default)
@fast-90
Copy link

fast-90 commented Jan 8, 2024

Hey, I'm back again with a question.

I am trying to get rope_autoimport working. I just briefly tried your gist and it worked for like a while, however it suddenly stopped working for me. Everything else is working, it's just that the rope_autoimport is not working. I have rope and python-lsp-server[rope] installed in my venv, and am using the same .dir-locals.el file in your gist.

As far as I can see, I also don't see any mention of "autoimport" in my Eglot events buffers anymore (it used to be there before).

Is it working correctly for you? Do you know how I can debug this in my case?

@doolio
Copy link
Author

doolio commented Jan 8, 2024

Is it working correctly for you? Do you know how I can debug this in my case?

I don't use rope and never have. I presume you have the third party plugin pylsp-rope installed in the same venv. Is other rope functionality working as you expect?

am using the same .dir-locals.el file in your gist

In the gist rope-autoimport is not enabled as by default it is disabled in python-lsp.

:rope_autoimport
(:code_actions (:enabled t) ; boolean: true (default) or false
               :completions (:enabled t) ; boolean: true (default) or false
               :enabled t ; boolean: true or false (default)
               :memory t) ; boolean: true or false (default)

Please confirm your settings are as follows. If not update your settings as above and test again.

Can you give me a minimal example to test if it is working for me?

@fast-90
Copy link

fast-90 commented Jan 8, 2024

@doolio sure, please see below:

Virtual environment

Install the following packages in your venv: python-lsp-server[rope] rope.

.dir-locals.el

I am using your snippet with the following amendments:

                                                 :rope_autoimport
                                                 (:code_actions (:enabled t) ; boolean: true (default) or false
                                                                :completions (:enabled t) ; boolean: true (default) or false
                                                                :enabled t ; boolean: true or false (default)
                                                                :memory t) ; boolean: true or false (default)
                                                 :rope_completion
                                                 (:eager :json-false ; boolean: true or false (default)
                                                         :enabled t) ; boolean: true or false (default)

I am using python-ts-mode instead of python-mode as well, but I don't think that should matter.

script.py

In an empty file, when you type something like mat, I would expect it to show a completion menu with the built-in package math as a suggestion to auto-import. Here is an example with some screenshots.

@doolio
Copy link
Author

doolio commented Jan 8, 2024

This is what I see with your settings. There is no other text in the test file.

image

Preceded by import I see:

image

and then later

image

These screenshots suggest it is working on my side.

I see several mentions (13) of "autoimport" in my *EGLOT events* buffer.

What is it that you see?

@fast-90
Copy link

fast-90 commented Jan 8, 2024

Yes, it seems to be working for you!

My Eglot events buffer does not mention anything about rope, let alone autoimport. I’m not sure why, as I’m sure the package and plugins are installed.

Copying over my whole events buffer might be oo much, but is there anything else I could do to find out what the issue is with my setup?

@doolio
Copy link
Author

doolio commented Jan 9, 2024

OK, so I'm still on Emacs 27.1 so am not using python-ts-mode. Maybe, that is the reason we are seeing different behaviours? What is your python and eglot configurations?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment