summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.rst6
-rw-r--r--doc/development_guide/api/index.rst3
-rw-r--r--doc/user_guide/installation/ide_integration/flymake-emacs.rst10
-rw-r--r--doc/whatsnew/fragments/7737.other5
-rw-r--r--elisp/pylint-flymake.el15
-rw-r--r--elisp/pylint.el255
-rw-r--r--elisp/startup17
-rw-r--r--pylint/__init__.py7
-rwxr-xr-xpylint/epylint.py11
-rw-r--r--tests/test_epylint.py27
-rw-r--r--tests/test_pylint_runners.py30
11 files changed, 70 insertions, 316 deletions
diff --git a/README.rst b/README.rst
index fd7267a29..f41ad3e23 100644
--- a/README.rst
+++ b/README.rst
@@ -86,11 +86,15 @@ Pylint ships with three additional tools:
- pyreverse_ (standalone tool that generates package and class diagrams.)
- symilar_ (duplicate code finder that is also integrated in pylint)
-- epylint_ (Emacs and Flymake compatible Pylint)
.. _pyreverse: https://pylint.pycqa.org/en/latest/pyreverse.html
.. _symilar: https://pylint.pycqa.org/en/latest/symilar.html
+
+The epylint_ Emacs package, which includes Flymake support, is now maintained
+in `its own repository`_.
+
.. _epylint: https://pylint.pycqa.org/en/latest/user_guide/ide_integration/flymake-emacs.html
+.. _its own repository: https://github.com/emacsorphanage/pylint
Projects that you might want to use alongside pylint include flake8_ (faster and simpler checks
with very few false positives), mypy_, pyright_ or pyre_ (typing checks), bandit_ (security
diff --git a/doc/development_guide/api/index.rst b/doc/development_guide/api/index.rst
index 373c49866..00e6e1a9f 100644
--- a/doc/development_guide/api/index.rst
+++ b/doc/development_guide/api/index.rst
@@ -7,10 +7,9 @@ Python program thanks to their APIs:
.. sourcecode:: python
- from pylint import run_pylint, run_epylint, run_pyreverse, run_symilar
+ from pylint import run_pylint, run_pyreverse, run_symilar
run_pylint("--disable=C", "myfile.py")
- run_epylint(...)
run_pyreverse(...)
run_symilar(...)
diff --git a/doc/user_guide/installation/ide_integration/flymake-emacs.rst b/doc/user_guide/installation/ide_integration/flymake-emacs.rst
index 44b9b3262..79310ff59 100644
--- a/doc/user_guide/installation/ide_integration/flymake-emacs.rst
+++ b/doc/user_guide/installation/ide_integration/flymake-emacs.rst
@@ -4,12 +4,10 @@ Using Pylint through Flymake in Emacs
=====================================
.. warning::
- If you're reading this doc and are actually using flymake please
- open a support question at https://github.com/PyCQA/pylint/issues/new/choose
- and tell us, we don't have any maintainers for emacs and are thinking about
- dropping the support.
-
-.. TODO 3.0, do we still need to support flymake ?
+ The Emacs package now has its own repository and is looking for a maintainer.
+ If you're reading this doc and are interested in maintaining this package or
+ are actually using flymake please open an issue at
+ https://github.com/emacsorphanage/pylint/issues/new/choose
To enable Flymake for Python, insert the following into your .emacs:
diff --git a/doc/whatsnew/fragments/7737.other b/doc/whatsnew/fragments/7737.other
new file mode 100644
index 000000000..7b7988759
--- /dev/null
+++ b/doc/whatsnew/fragments/7737.other
@@ -0,0 +1,5 @@
+epylint is now deprecated and will be removed in pylint 3.0.0. All emacs and flymake related
+files were removed and their support will now happen in an external repository :
+https://github.com/emacsorphanage/pylint.
+
+Closes #7737
diff --git a/elisp/pylint-flymake.el b/elisp/pylint-flymake.el
deleted file mode 100644
index ed213bf46..000000000
--- a/elisp/pylint-flymake.el
+++ /dev/null
@@ -1,15 +0,0 @@
-;; Configure Flymake for python
-(when (load "flymake" t)
- (defun flymake-pylint-init ()
- (let* ((temp-file (flymake-init-create-temp-buffer-copy
- 'flymake-create-temp-inplace))
- (local-file (file-relative-name
- temp-file
- (file-name-directory buffer-file-name))))
- (list "epylint" (list local-file))))
-
- (add-to-list 'flymake-allowed-file-name-masks
- '("\\.py\\'" flymake-pylint-init)))
-
-;; Set as a minor mode for python
-(add-hook 'python-mode-hook '(lambda () (flymake-mode)))
diff --git a/elisp/pylint.el b/elisp/pylint.el
deleted file mode 100644
index 327da0fcb..000000000
--- a/elisp/pylint.el
+++ /dev/null
@@ -1,255 +0,0 @@
-;;; pylint.el --- minor mode for running `pylint'
-
-;; Copyright (c) 2009, 2010 Ian Eure <ian.eure@gmail.com>
-;; Author: Ian Eure <ian.eure@gmail.com>
-;; Maintainer: Jonathan Kotta <jpkotta@gmail.com>
-
-;; Keywords: languages python
-;; Version: 1.02
-
-;; pylint.el is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; It is distributed in the hope that it will be useful, but WITHOUT ANY
-;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-;; details.
-;;
-;; You should have received a copy of the GNU General Public License along
-;; with your copy of Emacs; see the file COPYING. If not, write to the Free
-;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301, USA
-
-;;; Commentary:
-;;
-;; Specialized compile mode for pylint. You may want to add the
-;; following to your init.el:
-;;
-;; (autoload 'pylint "pylint")
-;; (add-hook 'python-mode-hook 'pylint-add-menu-items)
-;; (add-hook 'python-mode-hook 'pylint-add-key-bindings)
-;;
-;; There is also a handy command `pylint-insert-ignore-comment' that
-;; makes it easy to insert comments of the form `# pylint:
-;; ignore=msg1,msg2,...'.
-
-;;; Code:
-
-(require 'compile)
-(require 'tramp)
-
-(defgroup pylint nil
- "Minor mode for running the Pylint Python checker"
- :prefix "pylint-"
- :group 'tools
- :group 'languages)
-
-(defvar pylint-last-buffer nil
- "The most recent PYLINT buffer.
-A PYLINT buffer becomes most recent when you select PYLINT mode in it.
-Notice that using \\[next-error] or \\[compile-goto-error] modifies
-`completion-last-buffer' rather than `pylint-last-buffer'.")
-
-(defconst pylint-regexp-alist
- (let ((base "^\\(.*\\):\\([0-9]+\\):\s+\\(\\[%s.*\\)$"))
- (list
- (list (format base "[FE]") 1 2)
- (list (format base "[RWC]") 1 2 nil 1)))
- "Regexp used to match PYLINT hits. See `compilation-error-regexp-alist'.")
-
-(defcustom pylint-options '("--reports=n" "--output-format=parseable")
- "Options to pass to pylint.py"
- :type '(repeat string)
- :group 'pylint)
-
-(defcustom pylint-use-python-indent-offset nil
- "If non-nil, use `python-indent-offset' to set indent-string."
- :type 'boolean
- :group 'pylint)
-
-(defcustom pylint-command "pylint"
- "PYLINT command."
- :type '(file)
- :group 'pylint)
-
-(defcustom pylint-alternate-pylint-command "pylint2"
- "Command for pylint when invoked with C-u."
- :type '(file)
- :group 'pylint)
-
-(defcustom pylint-ask-about-save nil
- "Non-nil means \\[pylint] asks which buffers to save before compiling.
-Otherwise, it saves all modified buffers without asking."
- :type 'boolean
- :group 'pylint)
-
-(defvar pylint--messages-list ()
- "A list of strings of all pylint messages.")
-
-(defvar pylint--messages-list-hist ()
- "Completion history for `pylint--messages-list'.")
-
-(defun pylint--sort-messages (a b)
- "Compare function for sorting `pylint--messages-list'.
-
-Sorts most recently used elements first using `pylint--messages-list-hist'."
- (let ((idx 0)
- (a-idx most-positive-fixnum)
- (b-idx most-positive-fixnum))
- (dolist (e pylint--messages-list-hist)
- (when (string= e a)
- (setq a-idx idx))
- (when (string= e b)
- (setq b-idx idx))
- (setq idx (1+ idx)))
- (< a-idx b-idx)))
-
-(defun pylint--create-messages-list ()
- "Use `pylint-command' to populate `pylint--messages-list'."
- ;; example output:
- ;; |--we want this--|
- ;; v v
- ;; :using-cmp-argument (W1640): *Using the cmp argument for list.sort / sorted*
- ;; Using the cmp argument for list.sort or the sorted builtin should be avoided,
- ;; since it was removed in Python 3. Using either `key` or `functools.cmp_to_key`
- ;; should be preferred. This message can't be emitted when using Python >= 3.0.
- (setq pylint--messages-list
- (split-string
- (with-temp-buffer
- (shell-command (concat pylint-command " --list-msgs") (current-buffer))
- (flush-lines "^[^:]")
- (goto-char (point-min))
- (while (not (eobp))
- (delete-char 1) ;; delete ";"
- (re-search-forward " ")
- (delete-region (point) (line-end-position))
- (forward-line 1))
- (buffer-substring-no-properties (point-min) (point-max))))))
-
-;;;###autoload
-(defun pylint-insert-ignore-comment (&optional arg)
- "Insert a comment like \"# pylint: disable=msg1,msg2,...\".
-
-This command repeatedly uses `completing-read' to match known
-messages, and ultimately inserts a comma-separated list of all
-the selected messages.
-
-With prefix argument, only insert a comma-separated list (for
-appending to an existing list)."
- (interactive "*P")
- (unless pylint--messages-list
- (pylint--create-messages-list))
- (setq pylint--messages-list
- (sort pylint--messages-list #'pylint--sort-messages))
- (let ((msgs ())
- (msg "")
- (prefix (if arg
- ","
- "# pylint: disable="))
- (sentinel "[DONE]"))
- (while (progn
- (setq msg (completing-read
- "Message: "
- pylint--messages-list
- nil t nil 'pylint--messages-list-hist sentinel))
- (unless (string= sentinel msg)
- (add-to-list 'msgs msg 'append))))
- (setq pylint--messages-list-hist
- (delete sentinel pylint--messages-list-hist))
- (insert prefix (mapconcat 'identity msgs ","))))
-
-(define-compilation-mode pylint-mode "PYLINT"
- (setq pylint-last-buffer (current-buffer))
- (set (make-local-variable 'compilation-error-regexp-alist)
- pylint-regexp-alist)
- (set (make-local-variable 'compilation-disable-input) t))
-
-(defvar pylint-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map compilation-minor-mode-map)
- (define-key map " " 'scroll-up)
- (define-key map "\^?" 'scroll-down)
- (define-key map "\C-c\C-f" 'next-error-follow-minor-mode)
-
- (define-key map "\r" 'compile-goto-error) ;; ?
- (define-key map "n" 'next-error-no-select)
- (define-key map "p" 'previous-error-no-select)
- (define-key map "{" 'compilation-previous-file)
- (define-key map "}" 'compilation-next-file)
- (define-key map "\t" 'compilation-next-error)
- (define-key map [backtab] 'compilation-previous-error)
- map)
- "Keymap for PYLINT buffers.
-`compilation-minor-mode-map' is a cdr of this.")
-
-(defun pylint--make-indent-string ()
- "Make a string for the `--indent-string' option."
- (format "--indent-string='%s'"
- (make-string python-indent-offset ?\ )))
-
-;;;###autoload
-(defun pylint (&optional arg)
- "Run PYLINT, and collect output in a buffer, much like `compile'.
-
-While pylint runs asynchronously, you can use \\[next-error] (M-x next-error),
-or \\<pylint-mode-map>\\[compile-goto-error] in the grep \
-output buffer, to go to the lines where pylint found matches.
-
-\\{pylint-mode-map}"
- (interactive "P")
-
- (save-some-buffers (not pylint-ask-about-save) nil)
- (let* ((filename (buffer-file-name))
- (localname-offset (cl-struct-slot-offset 'tramp-file-name 'localname))
- (filename (or (and (tramp-tramp-file-p filename)
- (elt (tramp-dissect-file-name filename) localname-offset))
- filename))
- (filename (shell-quote-argument filename))
- (pylint-command (if arg
- pylint-alternate-pylint-command
- pylint-command))
- (pylint-options (if (not pylint-use-python-indent-offset)
- pylint-options
- (append pylint-options
- (list (pylint--make-indent-string)))))
- (command (mapconcat
- 'identity
- (append `(,pylint-command) pylint-options `(,filename))
- " ")))
-
- (compilation-start command 'pylint-mode)))
-
-;;;###autoload
-(defun pylint-add-key-bindings ()
- (let ((map (cond
- ((boundp 'py-mode-map) py-mode-map)
- ((boundp 'python-mode-map) python-mode-map))))
-
- ;; shortcuts in the tradition of python-mode and ropemacs
- (define-key map (kbd "C-c m l") 'pylint)
- (define-key map (kbd "C-c m p") 'previous-error)
- (define-key map (kbd "C-c m n") 'next-error)
- (define-key map (kbd "C-c m i") 'pylint-insert-ignore-comment)
- nil))
-
-;;;###autoload
-(defun pylint-add-menu-items ()
- (let ((map (cond
- ((boundp 'py-mode-map) py-mode-map)
- ((boundp 'python-mode-map) python-mode-map))))
-
- (define-key map [menu-bar Python pylint-separator]
- '("--" . pylint-separator))
- (define-key map [menu-bar Python next-error]
- '("Next error" . next-error))
- (define-key map [menu-bar Python prev-error]
- '("Previous error" . previous-error))
- (define-key map [menu-bar Python lint]
- '("Pylint" . pylint))
- nil))
-
-(provide 'pylint)
-
-;;; pylint.el ends here
diff --git a/elisp/startup b/elisp/startup
deleted file mode 100644
index 2f8fed1d4..000000000
--- a/elisp/startup
+++ /dev/null
@@ -1,17 +0,0 @@
-;; -*-emacs-lisp-*-
-;;
-;; Emacs startup file for the Debian GNU/Linux %PACKAGE% package
-;;
-;; Originally contributed by Nils Naumann <naumann@unileoben.ac.at>
-;; Modified by Dirk Eddelbuettel <edd@debian.org>
-;; Adapted for dh-make by Jim Van Zandt <jrv@vanzandt.mv.com>
-
-;; The %PACKAGE% package follows the Debian/GNU Linux 'emacsen' policy and
-;; byte-compiles its elisp files for each 'Emacs flavor' (emacs19,
-;; xemacs19, emacs20, xemacs20...). The compiled code is then
-;; installed in a subdirectory of the respective site-lisp directory.
-;; We have to add this to the load-path:
-(setq load-path (cons (concat "/usr/share/"
- (symbol-name debian-emacs-flavor)
- "/site-lisp/%PACKAGE%") load-path))
-(load-library "pylint")
diff --git a/pylint/__init__.py b/pylint/__init__.py
index ab5fd42ab..2cc7edadb 100644
--- a/pylint/__init__.py
+++ b/pylint/__init__.py
@@ -16,6 +16,7 @@ __all__ = [
import os
import sys
+import warnings
from collections.abc import Sequence
from typing import NoReturn
@@ -54,6 +55,12 @@ def run_epylint(argv: Sequence[str] | None = None) -> NoReturn:
"""
from pylint.epylint import Run as EpylintRun
+ warnings.warn(
+ "'run_epylint' will be removed in pylint 3.0, use "
+ "https://github.com/emacsorphanage/pylint instead.",
+ DeprecationWarning,
+ stacklevel=1,
+ )
EpylintRun(argv)
diff --git a/pylint/epylint.py b/pylint/epylint.py
index b6b6bf402..a69ce0d87 100755
--- a/pylint/epylint.py
+++ b/pylint/epylint.py
@@ -41,6 +41,7 @@ from __future__ import annotations
import os
import shlex
import sys
+import warnings
from collections.abc import Sequence
from io import StringIO
from subprocess import PIPE, Popen
@@ -168,6 +169,11 @@ def py_run(
To silently run Pylint on a module, and get its standard output and error:
>>> (pylint_stdout, pylint_stderr) = py_run( 'module_name.py', True)
"""
+ warnings.warn(
+ "'epylint' will be removed in pylint 3.0, use https://github.com/emacsorphanage/pylint instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
# Detect if we use Python as executable or not, else default to `python`
executable = sys.executable if "python" in sys.executable else "python"
@@ -198,6 +204,11 @@ def py_run(
def Run(argv: Sequence[str] | None = None) -> NoReturn:
+ warnings.warn(
+ "'epylint' will be removed in pylint 3.0, use https://github.com/emacsorphanage/pylint instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
if not argv and len(sys.argv) == 1:
print(f"Usage: {sys.argv[0]} <filename> [options]")
sys.exit(1)
diff --git a/tests/test_epylint.py b/tests/test_epylint.py
index e1b090395..7e9116e99 100644
--- a/tests/test_epylint.py
+++ b/tests/test_epylint.py
@@ -25,12 +25,12 @@ def example_path(tmp_path: PosixPath) -> PosixPath:
def test_epylint_good_command(example_path: PosixPath) -> None:
- out, err = lint.py_run(
- # pylint: disable-next=consider-using-f-string
- "%s -E --disable=E1111 --msg-template '{category} {module} {obj} {line} {column} {msg}'"
- % example_path,
- return_std=True,
- )
+ with pytest.warns(DeprecationWarning):
+ out, _ = lint.py_run(
+ f"{example_path} -E --disable=E1111 --msg-template "
+ "'{category} {module} {obj} {line} {column} {msg}'",
+ return_std=True,
+ )
msg = out.read()
assert (
msg
@@ -39,16 +39,16 @@ def test_epylint_good_command(example_path: PosixPath) -> None:
error my_app IvrAudioApp.run 4 8 Instance of 'IvrAudioApp' has no 'hassan' member
"""
)
- assert err.read() == ""
def test_epylint_strange_command(example_path: PosixPath) -> None:
- out, err = lint.py_run(
- # pylint: disable-next=consider-using-f-string
- "%s -E --disable=E1111 --msg-template={category} {module} {obj} {line} {column} {msg}"
- % example_path,
- return_std=True,
- )
+ with pytest.warns(DeprecationWarning):
+ out, _ = lint.py_run(
+ # pylint: disable-next=consider-using-f-string
+ "%s -E --disable=E1111 --msg-template={category} {module} {obj} {line} {column} {msg}"
+ % example_path,
+ return_std=True,
+ )
assert (
out.read()
== """\
@@ -66,4 +66,3 @@ def test_epylint_strange_command(example_path: PosixPath) -> None:
error
"""
)
- assert err.read() == ""
diff --git a/tests/test_pylint_runners.py b/tests/test_pylint_runners.py
index 8e68f8eaa..8d6930535 100644
--- a/tests/test_pylint_runners.py
+++ b/tests/test_pylint_runners.py
@@ -33,9 +33,7 @@ class _RunCallable(Protocol): # pylint: disable=too-few-public-methods
...
-@pytest.mark.parametrize(
- "runner", [run_epylint, run_pylint, run_pyreverse, run_symilar]
-)
+@pytest.mark.parametrize("runner", [run_pylint, run_pyreverse, run_symilar])
def test_runner(runner: _RunCallable, tmpdir: LocalPath) -> None:
filepath = os.path.abspath(__file__)
testargs = ["", filepath]
@@ -46,9 +44,18 @@ def test_runner(runner: _RunCallable, tmpdir: LocalPath) -> None:
assert err.value.code == 0
-@pytest.mark.parametrize(
- "runner", [run_epylint, run_pylint, run_pyreverse, run_symilar]
-)
+def test_epylint(tmpdir: LocalPath) -> None:
+ """TODO: 3.0 delete with epylint."""
+ filepath = os.path.abspath(__file__)
+ with tmpdir.as_cwd():
+ with patch.object(sys, "argv", ["", filepath]):
+ with pytest.raises(SystemExit) as err:
+ with pytest.warns(DeprecationWarning):
+ run_epylint()
+ assert err.value.code == 0
+
+
+@pytest.mark.parametrize("runner", [run_pylint, run_pyreverse, run_symilar])
def test_runner_with_arguments(runner: _RunCallable, tmpdir: LocalPath) -> None:
"""Check the runners with arguments as parameter instead of sys.argv."""
filepath = os.path.abspath(__file__)
@@ -59,6 +66,17 @@ def test_runner_with_arguments(runner: _RunCallable, tmpdir: LocalPath) -> None:
assert err.value.code == 0
+def test_epylint_with_arguments(tmpdir: LocalPath) -> None:
+ """TODO: 3.0 delete with epylint."""
+ filepath = os.path.abspath(__file__)
+ testargs = [filepath]
+ with tmpdir.as_cwd():
+ with pytest.raises(SystemExit) as err:
+ with pytest.warns(DeprecationWarning):
+ run_epylint(testargs)
+ assert err.value.code == 0
+
+
def test_pylint_argument_deduplication(
tmpdir: LocalPath, tests_directory: pathlib.Path
) -> None: