summaryrefslogtreecommitdiff
path: root/setuptools
diff options
context:
space:
mode:
authorAnderson Bravalheri <andersonbravalheri@gmail.com>2022-04-04 20:42:07 +0100
committerAnderson Bravalheri <andersonbravalheri@gmail.com>2022-04-05 10:44:50 +0100
commit00b4fb1aef3feb77f9db0cd05bfeb02d1fa1cf75 (patch)
treee95c911d4daa00954abdbf124580b4963cb77159 /setuptools
parentb686a319a2938019039c73aecba714970f9d6f74 (diff)
downloadpython-setuptools-git-00b4fb1aef3feb77f9db0cd05bfeb02d1fa1cf75.tar.gz
Simplify auto-discovered package_dir
If the directory follows a src-layout-ish, try harder to make `package_dir` in the form `{"": "src"}`. This might be later important for PEP 660 (e.g. when composing pth files or symlinking the toplevel packages).
Diffstat (limited to 'setuptools')
-rw-r--r--setuptools/config/expand.py27
-rw-r--r--setuptools/tests/config/test_expand.py32
2 files changed, 56 insertions, 3 deletions
diff --git a/setuptools/config/expand.py b/setuptools/config/expand.py
index ff9b2c9b..156d7473 100644
--- a/setuptools/config/expand.py
+++ b/setuptools/config/expand.py
@@ -312,8 +312,12 @@ def find_packages(
where = kwargs.pop('where', ['.'])
packages: List[str] = []
fill_package_dir = {} if fill_package_dir is None else fill_package_dir
+ find = list(unique_everseen(always_iterable(where)))
- for path in unique_everseen(always_iterable(where)):
+ if len(find) == 1 and all(not _same_path(find[0], x) for x in (".", root_dir)):
+ fill_package_dir.setdefault("", find[0])
+
+ for path in find:
package_path = _nest_path(root_dir, path)
pkgs = PackageFinder.find(package_path, **kwargs)
packages.extend(pkgs)
@@ -326,8 +330,27 @@ def find_packages(
return packages
+def _same_path(p1: _Path, p2: _Path) -> bool:
+ """Differs from os.path.samefile because it does not require paths to exist.
+ Purely string based (no comparison between i-nodes).
+ >>> _same_path("a/b", "./a/b")
+ True
+ >>> _same_path("a/b", "a/./b")
+ True
+ >>> _same_path("a/b", "././a/b")
+ True
+ >>> _same_path("a/b", "./a/b/c/..")
+ True
+ >>> _same_path("a/b", "../a/b/c")
+ False
+ >>> _same_path("a", "a/b")
+ False
+ """
+ return os.path.normpath(p1) == os.path.normpath(p2)
+
+
def _nest_path(parent: _Path, path: _Path) -> str:
- path = parent if path == "." else os.path.join(parent, path)
+ path = parent if path in {".", ""} else os.path.join(parent, path)
return os.path.normpath(path)
diff --git a/setuptools/tests/config/test_expand.py b/setuptools/tests/config/test_expand.py
index 3a59edbb..15053c8f 100644
--- a/setuptools/tests/config/test_expand.py
+++ b/setuptools/tests/config/test_expand.py
@@ -130,7 +130,7 @@ def test_resolve_class(tmp_path, package_dir, file, module, return_value):
({}, {"pkg", "other", "dir1", "dir1.dir2"}), # default value for `namespaces`
]
)
-def test_find_packages(tmp_path, monkeypatch, args, pkgs):
+def test_find_packages(tmp_path, args, pkgs):
files = {
"pkg/__init__.py",
"other/__init__.py",
@@ -153,3 +153,33 @@ def test_find_packages(tmp_path, monkeypatch, args, pkgs):
]
assert set(expand.find_packages(where=where, **args)) == pkgs
+
+
+@pytest.mark.parametrize(
+ "files, where, expected_package_dir",
+ [
+ (["pkg1/__init__.py", "pkg1/other.py"], ["."], {}),
+ (["pkg1/__init__.py", "pkg2/__init__.py"], ["."], {}),
+ (["src/pkg1/__init__.py", "src/pkg1/other.py"], ["src"], {"": "src"}),
+ (["src/pkg1/__init__.py", "src/pkg2/__init__.py"], ["src"], {"": "src"}),
+ (
+ ["src1/pkg1/__init__.py", "src2/pkg2/__init__.py"],
+ ["src1", "src2"],
+ {"pkg1": "src1/pkg1", "pkg2": "src2/pkg2"},
+ ),
+ (
+ ["src/pkg1/__init__.py", "pkg2/__init__.py"],
+ ["src", "."],
+ {"pkg1": "src/pkg1"},
+ ),
+ ],
+)
+def test_fill_package_dir(tmp_path, files, where, expected_package_dir):
+ write_files({k: "" for k in files}, tmp_path)
+ pkg_dir = {}
+ kwargs = {"root_dir": tmp_path, "fill_package_dir": pkg_dir, "namespaces": False}
+ pkgs = expand.find_packages(where=where, **kwargs)
+ assert set(pkg_dir.items()) == set(expected_package_dir.items())
+ for pkg in pkgs:
+ pkg_path = find_package_path(pkg, pkg_dir, tmp_path)
+ assert os.path.exists(pkg_path)