Repository: python-lsp/python-lsp-server
Pull request #318 (2022-12-24 10:59:00)

Ensure proper document match to avoid empty outline (Symbols)
... also if module_path is not a Path

Mileage may vary, but at least on my setup some sprinkled logging shows that `d.module_path` is not a `Path` (but rather string), so the comparison turns `False`, and so the result is an empty outline.  Wrapping it in `Path` should make it work whether or not it is a `Path`.

mnauw: As a sidenote, this has only become relevant since the change in commit 8fda905e72c102f9d4aec2cef071a2da12864d81, since before that this was handled by `os.path.samefile`.
ccordoba12: Thanks @mnauw for your help with this! Looks good to me but I'd like to ask @rear1019 what he thinks about it given that he was the one that made the `Path` comparison in the first place.

Patch:
diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml
index af235b1..7a398c0 100644
--- a/.github/workflows/static.yml
+++ b/.github/workflows/static.yml
@@ -9,6 +9,10 @@ on:
     branches:
       - '*'
 
+concurrency:
+  group: static-${{ github.ref }}
+  cancel-in-progress: true
+
 jobs:
   build:
     name: Static code analysis
diff --git a/pylsp/plugins/pycodestyle_lint.py b/pylsp/plugins/pycodestyle_lint.py
index 3702fdb..8cdcee5 100644
--- a/pylsp/plugins/pycodestyle_lint.py
+++ b/pylsp/plugins/pycodestyle_lint.py
@@ -2,8 +2,11 @@
 # Copyright 2021- Python Language Server Contributors.
 
 import logging
+
 import pycodestyle
+
 from pylsp import hookimpl, lsp
+from pylsp._utils import get_eol_chars
 
 try:
     from autopep8 import continued_indentation as autopep8_c_i
@@ -39,8 +42,18 @@ def pylsp_lint(workspace, document):
         kwargs = {k: v for k, v in opts.items() if v}
         styleguide = pycodestyle.StyleGuide(kwargs)
 
+        # Use LF to lint file because other line endings can give false positives.
+        # See spyder-ide/spyder#19565 for context.
+        source = document.source
+        eol_chars = get_eol_chars(source)
+        if eol_chars in ['\r', '\r\n']:
+            source = source.replace(eol_chars, '\n')
+            lines = source.splitlines(keepends=True)
+        else:
+            lines = document.lines
+
         c = pycodestyle.Checker(
-            filename=document.uri, lines=document.lines, options=styleguide.options,
+            filename=document.path, lines=lines, options=styleguide.options,
             report=PyCodeStyleDiagnosticReport(styleguide.options)
         )
         c.check_all()
diff --git a/pylsp/plugins/symbols.py b/pylsp/plugins/symbols.py
index 939dcda..d5925db 100644
--- a/pylsp/plugins/symbols.py
+++ b/pylsp/plugins/symbols.py
@@ -91,7 +91,7 @@ def pylsp_document_symbols(config, document):
                 else:
                     continue
 
-        if _include_def(d) and Path(document.path) == d.module_path:
+        if _include_def(d) and Path(document.path) == Path(d.module_path):
             tuple_range = _tuple_range(d)
             if tuple_range in exclude:
                 continue


Test patch:
diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml
index 5441d69..af6079b 100644
--- a/.github/workflows/test-linux.yml
+++ b/.github/workflows/test-linux.yml
@@ -9,6 +9,10 @@ on:
     branches:
       - '*'
 
+concurrency:
+  group: test-linux-${{ github.ref }}
+  cancel-in-progress: true
+
 jobs:
   build:
     name: Linux Py${{ matrix.PYTHON_VERSION }}
@@ -41,7 +45,7 @@ jobs:
       - run: pip install -e .[all,test]
       - name: Show test environment
         run: pip list
-      - run: pytest -v test/
+      - run: pytest --color=yes -v test/
       # Enable this if SSH debugging is required
       # - name: Setup tmate session
       #   uses: mxschmitt/action-tmate@v3
diff --git a/.github/workflows/test-mac.yml b/.github/workflows/test-mac.yml
index d00d6da..e111ff5 100644
--- a/.github/workflows/test-mac.yml
+++ b/.github/workflows/test-mac.yml
@@ -9,6 +9,10 @@ on:
     branches:
       - '*'
 
+concurrency:
+  group: test-mac-${{ github.ref }}
+  cancel-in-progress: true
+
 jobs:
   build:
     name: Mac Py${{ matrix.PYTHON_VERSION }}
@@ -41,7 +45,7 @@ jobs:
       - run: pip install -e .[all,test]
       - name: Show test environment
         run: pip list
-      - run: pytest -v test/
+      - run: pytest --color=yes -v test/
       # Enable this if SSH debugging is required
       # - name: Setup tmate session
       #   uses: mxschmitt/action-tmate@v3
diff --git a/.github/workflows/test-win.yml b/.github/workflows/test-win.yml
index 20eb7ea..eb393a9 100644
--- a/.github/workflows/test-win.yml
+++ b/.github/workflows/test-win.yml
@@ -9,6 +9,10 @@ on:
     branches:
       - '*'
 
+concurrency:
+  group: test-win-${{ github.ref }}
+  cancel-in-progress: true
+
 jobs:
   build:
     name: Win Py${{ matrix.PYTHON_VERSION }}
@@ -37,4 +41,4 @@ jobs:
       - run: pip install -e .[all,test]
       - name: Show test environment
         run: pip list
-      - run: pytest -v test/
+      - run: pytest --color=yes -v test/
diff --git a/test/plugins/test_pycodestyle_lint.py b/test/plugins/test_pycodestyle_lint.py
index e238147..0323356 100644
--- a/test/plugins/test_pycodestyle_lint.py
+++ b/test/plugins/test_pycodestyle_lint.py
@@ -2,6 +2,9 @@
 # Copyright 2021- Python Language Server Contributors.
 
 import os
+
+import pytest
+
 from pylsp import lsp, uris
 from pylsp.workspace import Document
 from pylsp.plugins import pycodestyle_lint
@@ -110,3 +113,22 @@ def test_pycodestyle_config(workspace):
     assert not [d for d in diags if d['code'] == 'W191']
     assert not [d for d in diags if d['code'] == 'E201']
     assert [d for d in diags if d['code'] == 'W391']
+
+
+@pytest.mark.parametrize('newline', ['\r\n', '\r'])
+def test_line_endings(workspace, newline):
+    """
+    Check that Pycodestyle doesn't generate false positives with line endings
+    other than LF.
+    """
+    # Create simple source that should give false positives
+    source = f"try:{newline}    1/0{newline}except Exception:{newline}    pass{newline}"
+
+    # Create document
+    doc = Document(DOC_URI, workspace, source)
+
+    # Get diagnostics
+    diags = pycodestyle_lint.pylsp_lint(workspace, doc)
+
+    # Assert no diagnostics were given
+    assert len(diags) == 0