Настройки dir-locals.el не применяются к некоторым переменным

Я хочу использовать свой .dir-locals.el для установки имени virtualenv в проекте. Переменная устанавливается, но не рассматривается при использовании в качестве аргумента в других объединенных переменных.

Я попытался добавить файл .dir-locals.el в проект Python. В нем я задаю корневое имя virtualenv для этого конкретного проекта. После этого я запускаю Emacs, открываю файл .py, чтобы проверить, изменены ли все необходимые переменные с именем virtualenv.

Часть моей конфигурации emacs, касающаяся режима python

;;; Python mode

(require 'python)
(ensure-package 'python-environment)
(require 'python-environment)
(ensure-package 'python-mode)
(require 'python-mode)
;;; dash used for pip-requirements
(ensure-package 'dash)
(require 'dash)
(require 'pip-requirements)
(require 'jedi-core)
(require 'company-jedi)


(defun init-python-mode()
  (setq-local tab-width 4)
  (setq-local indent-tabs-mode nil)
  (set (make-local-variable 'company-backends)
       '((company-jedi company-dabbrev-code)
         company-capf company-files))
  (setq python-environment-directory (expand-file-name "~/.virtualenvs")
      python-indent-guess-indent-offset nil
      python-indent-offset 4
      jedi:complete-on-dot t
      jedi:use-shortcuts t
      jedi:tooltip-method nil
      jedi:get-in-function-call-delay 0
      python-shell-interpreter (concat python-environment-directory
                                       "/" python-environment-default-root-name
                                       "/bin" "/python")
      jedi:server-command (list (concat python-environment-directory
                                        "/" python-environment-default-root-name
                                        "/bin" "/jediepcserver"))
      python-shell-interpreter (concat python-environment-directory
                                       "/" python-environment-default-root-name
                                       "/bin" "/python")
      flycheck-python-pylint-executable (concat python-environment-directory
                                                "/" python-environment-default-root-name
                                                "/bin" "/pylint")
      flycheck-python-flake8-executable (concat python-environment-directory
                                                "/" python-environment-default-root-name
                                                "/bin" "/flake8")
      flycheck-python-pycompile-executable (concat python-environment-directory
                                                   "/" python-environment-default-root-name
                                                   "/bin" "/python")
      )
  (flycheck-mode t)
)

(defun after-init-python-mode()
  (eldoc-mode -1)
  )

(define-key python-mode-map (kbd "C-c C-k") #'comment-dwim)

(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode))

(add-hook 'python-mode-hook #'init-python-mode)
(add-hook 'python-mode-hook #'jedi:setup)
(add-hook 'python-mode-hook #'after-init-python-mode)

Файл .dir-locals.el для проекта

;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")

((python-mode . ((python-environment-default-root-name . "abc")
         )))

Emacs, кажется, реагирует на переменные .dir-locals.el, которые, как я подтверждаю, безопасны при запуске. После этого, выполнив: 'describe-variable python-environment-default-root-name', я получаю это:

python-environment-default-root-name is a variable defined in ‘python-environment.el’.
Its value is "abc"
Original value was "default"
Local in buffer setup.py; global value is "default"

  This variable’s value is directory-local, set by the file
  ‘/home/mkj/dev/adm/.dir-locals.el’.

... что ожидается.

При выполнении: 'describe-variable jedi:server-command', 'describe-variable python-shell-interpreter', а также другие переменные, использующие python-environment-default-root-name, я получаю это:

jedi:server-command is a variable defined in ‘jedi-core.el’.
Its value is ("/home/mkj/.virtualenvs/default/bin/jediepcserver")

  This variable may be risky if used as a file-local variable.
python-shell-interpreter is a variable defined in ‘python.el’.
Its value is "/home/mkj/.virtualenvs/default/bin/python"
Original value was "python"

Мне кажется, что setq для имен переменных с использованием python-environment-default-root-name устанавливается только один раз, когда установлено значение по умолчанию, а значение .dir-locals.el игнорируется или устанавливается слишком поздно.

Есть ли здесь состояние гонки или это просто неправильный подход к установке переменных на основе virtualenv для режима python?


person user3540207    schedule 18.08.2019    source источник


Ответы (2)


Вы можете добавить вызов hack-local-variables в свой хук, чтобы сделать локальные каталоги доступными. Обычно только локальная переменная mode устанавливается до вашего хука, вызывая (hack-local-variables t). Вызовы, относящиеся к python-mode, вашему хуку и hack-local-variables, обычно выглядят так:

1 -> (normal-mode t)
| 2 -> (hack-local-variables t)
| 2 <- hack-local-variables: nil
| 2 -> (python-mode)
| | 3 -> (my-python-hook)
| | 3 <- my-python-hook: ("~/.virtualenvs/default/bin/jediepcserver")
| | 3 -> (hack-local-variables no-mode) ;; you want this called prior to your hook
| | 3 <- hack-local-variables: nil
| 2 <- python-mode: nil
1 <- normal-mode: t

Итак, вы можете изменить свой крючок,

(defun my-python-hook ()
  (hack-local-variables)
  ;; ...
  )

Однако это не кажется хорошим решением. Я не использую virtualenv, но мне кажется, что python-environment-virtualenv здесь уместно.

person Rorschach    schedule 18.08.2019
comment
Я бы предпочел не использовать hack-local-variables :-) - person user3540207; 19.08.2019
comment
Я не уверен, почему использование python-environment-virtualenv могло бы многое решить ... Похоже, это не влияет, например, на то, как flycheck нацеливает свои программы проверки. - person user3540207; 19.08.2019
comment
почему вы предпочитаете не использовать это? именно так читаются dir-locals... - person Rorschach; 19.08.2019
comment
как я уже сказал, я не использую virtualenv и не вникал в детали, но у большинства менеджеров версий есть механизм для связывания версии, которая не будет полагаться на взломы emacs. - person Rorschach; 19.08.2019

Я обнаружил, что elpy работает лучше для этой цели. Кажется, что он легко изменяет переменные для бэкэндов компании, интерпретаторов python, flycheck и т. д., без каких-либо хаков, просто изменяя переменную pyvenv-workon.

person user3540207    schedule 19.08.2019