hadialqattan / pycln

A formatter for finding and removing unused import statements.

Home Page:https://hadialqattan.github.io/pycln

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[BUG] Cleaning/checking fails with a READ permission error

ntrinquier opened this issue · comments

Short description

I have a Python project called kraken, which consists of several packages: kraken-core, kraken-common, and kraken-std. The code for each of these packages can be imported from kraken.core.X, kraken.common.X, and kraken.std.X, respectively. Note that there is no kraken root package, so it is impossible to import anything from kraken.X.

When, in a new project (called kraken-foo and from which I import from kraken.foo.X), there are unused imports, pycln tries to read an __init__.py file that does not exist (see below for a repro and my debugging steps).

Repro

  1. Clone kraken-foo.

  2. Run this Pycln command:

    $ pycln src --check
  3. Unexpected output (if present):

    ~/git/kraken-foo/src/kraken/__init__.py Permission denied [READ] [Errno 13] ⛔
    
    Oh no, there was an error! 💔 ☹️
    3 files would be left unchanged, 1 file has failed to be cleaned.

Expected behaviour:

Pycln should not attempt to read a file that does not exist.

Environment (please complete the following informations):

  • Python Version: Python 3.10
  • Pycln Version: 2.2.0
  • OS Type: MacOS

Context / debug

I have narrowed down the issue to this particular line:

return Path(path).joinpath(__INIT__)

which constructs a path to an __init__.py file, supposedly in the kraken package. However, as I pointed out in the description, we do not expect kraken to be a package, there are only kraken sub-packages.

If, in get_module_path, I return the path to __init__.py only when it exists, then the function returns None which makes the error go away, but does not correctly clean the files. I'm unsure about the way to properly fix it (presumably this function should return a path to a subpackage's __init__.py?), but I would be happy to try and contribute a fix with some guidance.

Hey @ntrinquier, I'm happy to see you around. I understood the problem and yeah that line might cause such a problem, but I tried to reproduce the bug but I couldn't:

ubuntu@Hadis-Laptop:~/projects/x$ git clone https://github.com/ntrinquier/kraken-foo
Cloning into 'kraken-foo'...
remote: Enumerating objects: 11, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 11 (delta 0), reused 11 (delta 0), pack-reused 0
Receiving objects: 100% (11/11), 46.88 KiB | 324.00 KiB/s, done.

ubuntu@Hadis-Laptop:~/projects/x$ cd kraken-foo/

ubuntu@Hadis-Laptop:~/projects/x/kraken-foo$ python3.10 -m pycln --version
pycln, version 2.2.0

ubuntu@Hadis-Laptop:~/projects/x/kraken-foo$ python3.10 -m pycln src --check
Looks good! ✨ 🍰 ✨
3 files would be left unchanged.

BTW, I'm using Ubutnu OS. So, kindly, try those combinations of commands again and let me know if the problem still there. then I'll try to find a way to test that on MacOS.

Thank you.

@hadialqattan Here are the exact commands I used:

git clone https://github.com/ntrinquier/kraken-foo && cd kraken-foo
poetry install && poetry run pycln --version
poetry run pycln src --check

(Note that I am installing and running pycln with poetry, in case it makes a difference)

image

@ntrinquier I discovered that running Pycln using Poetry is the only case where this issue raise (or maybe using a virtual env in general). I knew that you were willing to provide a fix (and I appreciate that). But after doing some investigation I found that providing a workaround-ish fix may be easier, less risky, and more sufficient than fixing the actual problem (generating a non-existing init.py file path)*. So I opened a PR #215 and if you don't mind I want you to try it and let me know if that really fixed the problem (and perhaps give me your thoughts). Then I'll try to finalize the PR (adding docs/tests) to include the fix in the next release.

Thanks a lot for your support 🙏🏻.


* Fixing the actual problem might open a door for other problems like identifying modules etc... . So, I thought about it in this way, why don't I do a workaround-ish fix that's both sufficient and doesn't has the potential of exposing other problems? then I came across the provided solution in PR #215.

Thanks @hadialqattan. I tried #215, and while it makes the error disappear, it does not remove unused imports. It is still an improvement compared to the current situation, but I was wondering if there was a way to fix that as well?

it does not remove unused imports.

@ntrinquier Well, I think you should try the --all flag.


$ poetry run pycln src --all --check

Ref: --all


Also see: __init__ without all situation and --disable-all-dunder-policy

it does not remove unused imports.

@ntrinquier Well, I think you should try the --all flag.

$ poetry run pycln src --all --check

Ref: --all

Also see: __init__ without all situation and --disable-all-dunder-policy

Right, indeed! Then I think this is OK, I will wait for your MR to be merged and released :)

@ntrinquier Pycln v2.2.1 is waiting for you. Have a good day.