Commit c4018503 by Steph Samson Committed by Sébastien Eustace

Handle nested wildcards in package includes correctly. Fixes: #1379. (#1592)

* Handle nested wildcards in package includes correctly. Fixes: #1379.

Use compat `Path`.

* Ensure that when building sdists, subpackages with Python files (but not necessarily an __init__.py file) will be included.
parent 5050362f
...@@ -237,7 +237,7 @@ class SdistBuilder(Builder): ...@@ -237,7 +237,7 @@ class SdistBuilder(Builder):
if from_top_level == ".": if from_top_level == ".":
continue continue
is_subpkg = "__init__.py" in filenames is_subpkg = any([filename.endswith(".py") for filename in filenames])
if is_subpkg: if is_subpkg:
subpkg_paths.add(from_top_level) subpkg_paths.add(from_top_level)
parts = from_top_level.split(os.sep) parts = from_top_level.split(os.sep)
......
...@@ -12,7 +12,6 @@ class PackageInclude(Include): ...@@ -12,7 +12,6 @@ class PackageInclude(Include):
base = base / source base = base / source
super(PackageInclude, self).__init__(base, include, formats=formats) super(PackageInclude, self).__init__(base, include, formats=formats)
self.check_elements() self.check_elements()
@property @property
...@@ -35,6 +34,8 @@ class PackageInclude(Include): ...@@ -35,6 +34,8 @@ class PackageInclude(Include):
return self.check_elements() return self.check_elements()
def check_elements(self): # type: () -> PackageInclude def check_elements(self): # type: () -> PackageInclude
root = self._elements[0]
if not self._elements: if not self._elements:
raise ValueError( raise ValueError(
"{} does not contain any element".format(self._base / self._include) "{} does not contain any element".format(self._base / self._include)
...@@ -44,20 +45,24 @@ class PackageInclude(Include): ...@@ -44,20 +45,24 @@ class PackageInclude(Include):
# Probably glob # Probably glob
self._is_package = True self._is_package = True
# The __init__.py file should be first # Packages no longer need an __init__.py in python3, but there must
root = self._elements[0] # at least be one .py file for it to be considered a package
if root.name != "__init__.py": if not any([element.suffix == ".py" for element in self._elements]):
raise ValueError("{} is not a package.".format(root)) raise ValueError("{} is not a package.".format(root.name))
self._package = root.parent.name self._package = root.parent.name
else: else:
if self._elements[0].is_dir(): if root.is_dir():
# If it's a directory, we include everything inside it # If it's a directory, we include everything inside it
self._package = self._elements[0].name self._package = root.name
self._elements = sorted(list(self._elements[0].glob("**/*"))) self._elements = sorted(list(root.glob("**/*")))
if not any([element.suffix == ".py" for element in self._elements]):
raise ValueError("{} is not a package.".format(root.name))
self._is_package = True self._is_package = True
else: else:
self._package = self._elements[0].stem self._package = root.stem
self._is_module = True self._is_module = True
return self return self
...@@ -265,6 +265,7 @@ def test_complete_no_vcs(): ...@@ -265,6 +265,7 @@ def test_complete_no_vcs():
"my_package/sub_pkg1/__init__.py", "my_package/sub_pkg1/__init__.py",
"my_package/sub_pkg2/__init__.py", "my_package/sub_pkg2/__init__.py",
"my_package/sub_pkg2/data2/data.json", "my_package/sub_pkg2/data2/data.json",
"my_package/sub_pkg3/foo.py",
"my_package-1.2.3.dist-info/entry_points.txt", "my_package-1.2.3.dist-info/entry_points.txt",
"my_package-1.2.3.dist-info/LICENSE", "my_package-1.2.3.dist-info/LICENSE",
"my_package-1.2.3.dist-info/WHEEL", "my_package-1.2.3.dist-info/WHEEL",
......
...@@ -124,6 +124,7 @@ def test_make_setup(): ...@@ -124,6 +124,7 @@ def test_make_setup():
"my_package", "my_package",
"my_package.sub_pkg1", "my_package.sub_pkg1",
"my_package.sub_pkg2", "my_package.sub_pkg2",
"my_package.sub_pkg3",
] ]
assert ns["install_requires"] == ["cachy[msgpack]>=0.2.0,<0.3.0", "cleo>=0.6,<0.7"] assert ns["install_requires"] == ["cachy[msgpack]>=0.2.0,<0.3.0", "cleo>=0.6,<0.7"]
assert ns["entry_points"] == { assert ns["entry_points"] == {
...@@ -178,6 +179,7 @@ def test_find_files_to_add(): ...@@ -178,6 +179,7 @@ def test_find_files_to_add():
Path("my_package/sub_pkg1/__init__.py"), Path("my_package/sub_pkg1/__init__.py"),
Path("my_package/sub_pkg2/__init__.py"), Path("my_package/sub_pkg2/__init__.py"),
Path("my_package/sub_pkg2/data2/data.json"), Path("my_package/sub_pkg2/data2/data.json"),
Path("my_package/sub_pkg3/foo.py"),
Path("pyproject.toml"), Path("pyproject.toml"),
] ]
) )
...@@ -213,7 +215,12 @@ def test_find_packages(): ...@@ -213,7 +215,12 @@ def test_find_packages():
pkg_dir, packages, pkg_data = builder.find_packages(include) pkg_dir, packages, pkg_data = builder.find_packages(include)
assert pkg_dir is None assert pkg_dir is None
assert packages == ["my_package", "my_package.sub_pkg1", "my_package.sub_pkg2"] assert packages == [
"my_package",
"my_package.sub_pkg1",
"my_package.sub_pkg2",
"my_package.sub_pkg3",
]
assert pkg_data == { assert pkg_data == {
"": ["*"], "": ["*"],
"my_package": ["data1/*"], "my_package": ["data1/*"],
......
import pytest
from poetry.masonry.utils.package_include import PackageInclude
from poetry.utils._compat import Path
fixtures_dir = Path(__file__).parent / "fixtures"
with_includes = fixtures_dir / "with_includes"
def test_package_include_with_multiple_dirs():
pkg_include = PackageInclude(base=fixtures_dir, include="with_includes")
assert pkg_include.elements == [
with_includes / "__init__.py",
with_includes / "bar",
with_includes / "bar/baz.py",
with_includes / "extra_package",
with_includes / "extra_package/some_dir",
with_includes / "extra_package/some_dir/foo.py",
with_includes / "extra_package/some_dir/quux.py",
with_includes / "not_a_python_pkg",
with_includes / "not_a_python_pkg/baz.txt",
]
def test_package_include_with_simple_dir():
pkg_include = PackageInclude(base=with_includes, include="bar")
assert pkg_include.elements == [with_includes / "bar/baz.py"]
def test_package_include_with_nested_dir():
pkg_include = PackageInclude(base=with_includes, include="extra_package/**/*.py")
assert pkg_include.elements == [
with_includes / "extra_package/some_dir/foo.py",
with_includes / "extra_package/some_dir/quux.py",
]
def test_package_include_with_no_python_files_in_dir():
with pytest.raises(ValueError) as e:
PackageInclude(base=with_includes, include="not_a_python_pkg")
assert str(e.value) == "not_a_python_pkg is not a package."
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment