jorgenschaefer / elpy

Emacs Python Development Environment
GNU General Public License v3.0
1.9k stars 261 forks source link

Elpy fails with Python 3.12, distutils has been removed #2051

Open robewald opened 3 weeks ago

robewald commented 3 weeks ago

Summary

Python 3.12 has removed distutils Therefore the rpc initialization script fails.

Steps to reproduce

My configuration

OS

Mac OS Sonoma 14.6.1 homebrew install pipx python@3.12 virtualenv

Result of (elpy-config)

Elpy Configuration

Emacs.............: 29.4
Elpy..............: Not found (Python), 1.35.0 (Emacs Lisp)
Virtualenv........: py_docker (/Users/robert/.virtualenvs/py_docker/)
Interactive Python: python3 3.12.6 (/Users/robert/.virtualenvs/py_docker/bin/python3)
RPC virtualenv....: rpc-venv (/Users/robert/.emacs.d/elpy/rpc-venv)
 Python...........: python3 nil (/Users/robert/.emacs.d/elpy/rpc-venv/bin/python3)
 Jedi.............: Not found
 Autopep8.........: Not found
 Yapf.............: Not found
 Black............: Not found
Syntax checker....: Not found (flake8)

Warnings

The Python interpreter could not find the elpy module. Please report
to: https://github.com/jorgenschaefer/elpy/issues/new.

There was an unexpected problem starting the RPC process. Please check
the following output to see if this makes sense to you. To me, it
doesn't.

Traceback (most recent call last):
  File "<string>", line 9, in <module>
ModuleNotFoundError: No module named 'distutils'
genovese commented 6 days ago

I too have this problem, which causes spurious syntax error highlighting with new syntax.

From a quick look, it appears that distutils is only needed for LooseVersion, and this is only used for a version comparison. There are two packages that seem to have reasonable and likely sufficient replacements for LooseVersion: packaging.version (in packaging) and looseversion. The former seems more established, so you could perhaps replace

from distutils.version import LooseVersion

with

try:
    from distutils.version import LooseVersion
except ModuleNotFoundError:
    from packaging.version import parse as LooseVersion

or similarly with the looseversion package which is intended as a drop-in replacement.

genovese commented 6 days ago

An update: Making this change solved the problem for me.

I made this adjustment to the variable elpy-config--get-config in elpy.el and made a python 3.12 virtual env ~/.emacs.d/elpy/new-rpc-venv and set elpy-rpc-virtualenv-path to that directory. It turns out that packaging is installed as part of the other installations in the venv (black, flake8, ...) and so the modified code just works.

genovese commented 6 days ago

P.S. elpy/blackutil.py and elpy/jedybackend.py use pkg_resources which is also deprecated and removed in Python 3.12. This raises a messsage from the elpy backend but is not fatal. All that is used is pkg_resources.parse_version, so perhaps packaging.parse can be used instead. Alternatively, pkg_resources has been moved from the standard library to setuptools apparently.

I'll experiment with changing this when I have a moment, but I thought I'd mention in as a follow up to the earlier comments. Thanks

P.P.S. The new version is recognized and seems to function, but there do appear to still be some issues using the new version. I haven't tracked down the problem, so it's not as cleancut as I had hoped.