Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] certain editable installs allow case-insensitive imports #3994

Closed
aganders3 opened this issue Jul 27, 2023 · 3 comments · Fixed by #3995
Closed

[BUG] certain editable installs allow case-insensitive imports #3994

aganders3 opened this issue Jul 27, 2023 · 3 comments · Fixed by #3995
Labels
bug Needs Triage Issues that need to be evaluated for severity and status.

Comments

@aganders3
Copy link
Contributor

aganders3 commented Jul 27, 2023

setuptools version

setuptools==68.0.0

Python version

Python 3.10.12

OS

macOS

Additional environment information

I believe this is only a problem on macOS because of its case-preserving but case-insensitive filesytem. I'm not too familiar with filesystems but it may be a problem on others. See also PEP 235 - Import on Case-Insensitive Platforms.

I think this also depends on exactly how it is installed, but I'm not familiar with what determines which editable installation method is used.

Description

I have a project with the following structure:

├── pyproject.toml
├── setup.cfg
└── setuptools_editable_case_insensitive
    ├── __init__.py
    └── module_1.py

When the package is installed as editable, I am able to import module_1 with arbitrary case:

>>> from setuptools_editable_case_insensitive import module_1
>>> from setuptools_editable_case_insensitive import MODULE_1
>>> import setuptools_editable_case_insensitive.Module_1

Expected behavior

I expected to get an ImportError when importing a module with incorrect case, as is the behavior when installed normally:

>>> from setuptools_editable_case_insensitive import Module_1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name 'Module_1' from 'setuptools_editable_case_insensitive' (/Users/aandersoniii/src/setuptools-example/setuptools_editable_case_insensitive/__init__.py)

How to Reproduce

  1. Clone this simplified example: git clone git@github.com:aganders3/setuptools-editable-case-insensitive.git
  2. Create a virtual environment: cd setuptools-editable-case-insensitive && python3.10 -m venv venv && source venv/bin/activate
  3. Install the project as editable: pip install -e .
  4. Run the test script: python test_imports.py
  5. Note module_1 is successfully imported with arbitrary case

Output

git clone git@github.com:aganders3/setuptools-editable-case-insensitive.git
Cloning into 'setuptools-editable-case-insensitive'...
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 7 (delta 0), reused 7 (delta 0), pack-reused 0
Receiving objects: 100% (7/7), done.cd setuptools-editable-case-insensitive && python3.10 -m venv venv && source venv/bin/activatepip install -e .
Obtaining file:///Users/aandersoniii/src/setuptools-editable-case-insensitive
  Installing build dependencies ... done
  Checking if build backend supports build_editable ... done
  Getting requirements to build editable ... done
  Installing backend dependencies ... done
  Preparing editable metadata (pyproject.toml) ... done
Building wheels for collected packages: setuptools-editable-case-insensitive
  Building editable for setuptools-editable-case-insensitive (pyproject.toml) ... done
  Created wheel for setuptools-editable-case-insensitive: filename=setuptools_editable_case_insensitive-0.0.0-0.editable-py3-none-any.whl size=2787 sha256=580be31a2260f44e9e877f905ac5875526d31d0f46a433eb72b9103b55f7cb31
  Stored in directory: /private/var/folders/dd/w2cggkp91dq_xn53d6fphp8c0000gq/T/pip-ephem-wheel-cache-ik0hfo9g/wheels/a7/9d/6e/26a7dd6200d0678dcfb12a1d9447413c2a95d67d6a00fefc74
Successfully built setuptools-editable-case-insensitive
Installing collected packages: setuptools-editable-case-insensitive
Successfully installed setuptools-editable-case-insensitive-0.0.0python test_imports.py 
Hello from setuptools_editable_case_insensitive.module_1!
Hooray, I was imported with the correct name!
	__name__='setuptools_editable_case_insensitive.module_1'
	__file__='/Users/aandersoniii/src/setuptools-editable-case-insensitive/setuptools_editable_case_insensitive/module_1.py'

Hello from setuptools_editable_case_insensitive.Module_1!
Oh no, I was imported with the wrong name!
	__name__='setuptools_editable_case_insensitive.Module_1'
	__file__='/Users/aandersoniii/src/setuptools-editable-case-insensitive/setuptools_editable_case_insensitive/Module_1.py'
@aganders3 aganders3 added bug Needs Triage Issues that need to be evaluated for severity and status. labels Jul 27, 2023
@aganders3
Copy link
Contributor Author

This seems to be a problem when using the _EditableFinder. I can open a PR with a potential fix if it is welcome.

@abravalheri
Copy link
Contributor

abravalheri commented Jul 27, 2023

Hi @aganders3 a PR would be very useful, thank you for working on that.

For the finder we use pathlib.Path.exists and importlib.utils.spec_from_file_location. Do you know if these functions also suffer from the same problem?

@aganders3
Copy link
Contributor Author

Yes, that's basically the problem. pathlib.Path.exists will return True even with the wrong case on macOS. Likewise spec_from_file_location will return a spec.

My proposed fix is in #3995 but feedback is appreciated. I am curious if a similar fix would be needed for namespace packages, but I don't know too much about them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Needs Triage Issues that need to be evaluated for severity and status.
Projects
None yet
2 participants