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.31k stars 1.14k forks source link

wrong-import-order for third party libraries depends on working directory #8801

Open tan-wei-xin-alez opened 1 year ago

tan-wei-xin-alez commented 1 year ago

Bug description

The working directory from where pylint binary was run influences whether it outputs the wrong-import-order coding convention error or not

Configuration

Given the following directory structure

root_dir
└── repo_dir
    ├── pyproject.toml
    └── src
        ├── module1
        │   ├── function1.py
        │   └── __init__.py
        └── module2
            ├── function2.py
            └── __init__.py

with the following file contents

[project] name = "pylint-wrong-import-order-bug-minimal-example" version = "0.0.1" requires-python = ">=3.11" dependencies = [ "pylint" ]


- src/module1/function1.py

'''Module 1 '''

import module2

import pylint

def function1(): '''Function 1 ''' module2.function2() print(f"{pylint.version}")

if name == "main": function1()


- src/module1/\_\_init\_\_.py

'''Init for module1 '''


- src/module2/function2.py

'''Module 2 '''

def function2(): '''Function 2 '''


- src/module2/\_\_init\_\_.py

'''Init for module2 '''

from .function2 import function2


The following is only thrown when the working directory where `pylint` is run is "repo_dir"

***** Module module1.function1 src/module1/function1.py:6:0: C0411: third party import "import pylint" should be placed before "import module2" (wrong-import-order)


### Command used

```shell
pylint ${HOME}/root_dir/repo_dir/src/module1 ${HOME}/root_dir/repo_dir/src/module2

Pylint output

Working directory root_dir repo_dir
Output
--------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)
************* Module module1.function1
src/module1/function1.py:6:0: C0411: third party import "import pylint" should be placed before "import module2" (wrong-import-order)

-------------------------------------------------------------------
Your code has been rated at 8.89/10 (previous run: 10.00/10, -1.11)

Expected behavior

pylint output should be the same regardless of where it was run from so long as settings are the same

Pylint version

pylint 2.17.4
astroid 2.15.5
Python 3.11.3 (main, Jun  7 2023, 20:38:35) [GCC 9.4.0]

OS / Environment

➜  ~ cat /etc/os-release     
NAME="Ubuntu"
VERSION="20.04.6 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.6 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
➜  ~ uname -r           
5.15.0-72-generic
➜  ~ pdm --version                                               
PDM, version 2.7.0

Additional dependencies

Compiled with pdm update --project root_dir/repo_dir

tan-wei-xin-alez commented 1 year ago

Workaround used in my case was cwd parameter since pylint was being called via subprocess module e.g.

pylint_output = subprocess.check_output(
  cwd=<working_directory_path>,
  args=["pylint", <args>],
  stderr=subprocess.STDOUT
).decode("utf-8")
jacobtylerwalls commented 1 year ago

Hi, thanks for the report.

pylint depends on isort's determination of what's first-party and third-party. I set up your minimal example (which is excellent!), replaced pylint with another package (because I have my editable install of pylint on my path), and I ran isort path/to/package from repo_dir and from root_dir and observed the same difference.

For that reason, I don't think there is a functional issue here. This does come up with some frequency (see #4437), so I think we should update the docs to indicate that if you want to lint a package, you should probably cd to that package.


pylint output should be the same regardless of where it was run from so long as settings are the same

In other words, I don't think that's part of pylint's contract, since sys.path depends on the working directory.

tan-wei-xin-alez commented 1 year ago

@jacobtylerwalls would it not be possible to introduce something like a cwd parameter to pylint? Would make it more explicit for users who are forced to run pylint from other directories

jacobtylerwalls commented 1 year ago

Possibly, but if the only reason for it is to give information to isort, I'm wondering if it's better to just configure isort. Does adding module1 and module2 as known first-party imports help?

tan-wei-xin-alez commented 1 year ago

@jacobtylerwalls oh didn't see that option, only saw known-third-party imports in the rcfile I was using, that makes a lot more sense, should have searched that up more thoroughly σ(^_^;)