Skip to content

Commit ab27633

Browse files
committed
Fix derivation of local package names in Pipfile
Fixes pypa#6409
1 parent 861b3c6 commit ab27633

File tree

2 files changed

+69
-7
lines changed

2 files changed

+69
-7
lines changed

pipenv/utils/dependencies.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -684,9 +684,10 @@ def find_package_name_from_directory(directory):
684684
directory_path = Path(directory_str[1:])
685685

686686
try:
687-
# Sort contents - directories first, then files
687+
# Sort contents - files first, then directories to search parent
688+
# directories before leaf directories.
688689
directory_contents = sorted(
689-
directory_path.iterdir(), key=lambda x: (x.is_file(), x.name)
690+
directory_path.iterdir(), key=lambda x: (x.is_dir(), x.name)
690691
)
691692

692693
for path in directory_contents:
@@ -844,31 +845,31 @@ def determine_package_name(package: InstallRequirement):
844845

845846

846847
def find_package_name_from_filename(filename, file):
847-
if filename.endswith("METADATA"):
848+
if filename == "METADATA":
848849
content = file.read().decode()
849850
possible_name = parse_metadata_file(content)
850851
if possible_name:
851852
return possible_name
852853

853-
if filename.endswith("PKG-INFO"):
854+
if filename == "PKG-INFO":
854855
content = file.read().decode()
855856
possible_name = parse_pkginfo_file(content)
856857
if possible_name:
857858
return possible_name
858859

859-
if filename.endswith("setup.py"):
860+
if filename == "setup.py":
860861
content = file.read().decode()
861862
possible_name = parse_setup_file(content)
862863
if possible_name:
863864
return possible_name
864865

865-
if filename.endswith("setup.cfg"):
866+
if filename == "setup.cfg":
866867
content = file.read().decode()
867868
possible_name = parse_cfg_file(content)
868869
if possible_name:
869870
return possible_name
870871

871-
if filename.endswith("pyproject.toml"):
872+
if filename == "pyproject.toml":
872873
content = file.read().decode()
873874
possible_name = parse_toml_file(content)
874875
if possible_name:
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import os
2+
from pathlib import Path
3+
4+
import pytest
5+
6+
7+
@pytest.mark.install
8+
@pytest.mark.needs_internet
9+
@pytest.mark.skipif(
10+
os.name == "nt",
11+
reason="This test is not for Windows",
12+
)
13+
def test_install_path_with_nested_setup_module(pipenv_instance_pypi):
14+
with pipenv_instance_pypi() as p:
15+
# Create a simple package.
16+
package_dir = Path(p.path) / "simple_package"
17+
package_dir.mkdir()
18+
19+
# Create a simple setup.py file
20+
with open(package_dir / "setup.py", "w") as f:
21+
f.write("""
22+
from setuptools import setup, find_packages
23+
24+
setup(
25+
name="simple-package",
26+
version="0.1.0",
27+
packages=find_packages(),
28+
)
29+
""")
30+
module_dir = package_dir / "simple_package"
31+
module_dir.mkdir()
32+
33+
(module_dir / "__init__.py").touch()
34+
35+
# Create the package module
36+
with open(module_dir / "setup.py", "w") as f:
37+
f.write("""
38+
def setup(name = ''):
39+
return f'Setup package {name}'
40+
41+
def configure():
42+
return setup(name='my_simple_package')
43+
""")
44+
45+
# Install the package using a path with spaces
46+
# Use both escaped spaces and quoted path to test both scenarios
47+
relative_package_dir = package_dir.relative_to(p.path)
48+
c = p.pipenv(f'install -e {relative_package_dir}')
49+
assert c.returncode == 0
50+
51+
# Verify the package was installed correctly
52+
c = p.pipenv('run python -c "'
53+
'from simple_package import setup; '
54+
'print(setup.configure())"')
55+
assert c.returncode == 0
56+
assert "Setup package my_simple_package" in c.stdout
57+
58+
# Ensure my_simple_package was not parsed from the setup.py module
59+
# inside the package.
60+
with open(Path(p.path) / "Pipfile", "r") as f:
61+
assert "my_simple_package" not in f.read()

0 commit comments

Comments
 (0)