pylint-dev / pylint

It's not just a linter that annoys you!
https://pylint.readthedocs.io/en/latest/
GNU General Public License v2.0
5.24k stars 1.12k forks source link

docstyle doesn't work with --from-stdin #9053

Open jeremybettis opened 12 months ago

jeremybettis commented 12 months ago

Bug description

When using --from-stdin, the docstyle plugin still reads the file directly. If the line where the doc string is in stdin happens to match with another string in the file on disk, then it will give an error about an invalid docstring quote.

In a situation where you might be running pylint from a git commit that is not the current working copy, this could be very common.

This patch would fix the issue, but it's not very efficient, doesn't check for exceptions, etc.

--- pylint/extensions/docstyle.py        2023-09-19 15:31:45.561690710 -0600
+++ pylint/extensions/docstyle-fixed.py  2023-09-19 15:31:55.425789319 -0600
@@ -65,7 +65,11 @@

         if docstring:
             lineno = node.fromlineno + 1
-            line = linecache.getline(node.root().file, lineno).lstrip()
+            root = node.root()
+            if root.file_bytes:
+                line = str(root.file_bytes.split(b"\n")[lineno-1]).lstrip()
+            else:
+                line = linecache.getline(root.file, lineno).lstrip()
             if line and line.find('"""') == 0:
                 return
             if line and "'''" in line:

Configuration

No response

Command used

Create 2 files

hello.py

"""This is a module docstring"""

def hello():
    """This is a function docstring"""
    arr = [
        "hello",
        "world"
    ]
    return arr

hello_modified.py

"""This is a module docstring"""

# This file has two lines added
# line 2

def hello():
    """This is a function docstring"""
    arr = [
        "hello",
        "world"
    ]
    return arr

Run this command: cat hello_modified.py | pylint --from-stdin --load-plugins=pylint.extensions.docstyle hello.py

Pylint output

************* Module hello
hello.py:6:0: C0198: Bad docstring quotes in function, expected """, given " (bad-docstring-quotes)

------------------------------------------------------------------
Your code has been rated at 6.67/10 (previous run: 6.67/10, +0.00)

Expected behavior

I expected that there would be no errors, just as if running pylint directly on hello_modified.py

Pylint version

pylint 2.13.8
astroid 2.11.3
Python 3.8.10+chromium.25 (default, Sep 27 2022, 04:18:13) 
[GCC 10.2.1 20210130 (Red Hat 10.2.1-11)]

OS / Environment

Debian GNU/Linux rodete 20230901.00.02RD

Additional dependencies

No response

mbyrnepr2 commented 11 months ago

Interesting one @jeremybettis and thanks for the report. Perhaps we could simplify further and remove the linecache part altogether:

--- a/pylint/extensions/docstyle.py
+++ b/pylint/extensions/docstyle.py
@@ -60,12 +60,15 @@ class DocStringStyleChecker(checkers.BaseChecker):
                 confidence=HIGH,
             )

-        # Use "linecache", instead of node.as_string(), because the latter
-        # looses the original form of the docstrings.
-
+        # Use this approach instead of node.as_string(), because the latter
+        # loses the original form of the docstrings.
         if docstring:
-            lineno = node.fromlineno + 1
-            line = linecache.getline(node.root().file, lineno).lstrip()
+            with node.root().stream() as stream:
+                for number, line in enumerate(stream):
+                    if number == node.fromlineno:
+                        line = line.decode().lstrip()
+                        break
+
             if line and line.find('"""') == 0:
                 return
             if line and "'''" in line: