Skip to content

Commit

Permalink
Handle nested wildcards in package includes correctly. Fixes: #1379. (#…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
kasteph authored and sdispater committed Jan 7, 2020
1 parent 5050362 commit c401850
Show file tree
Hide file tree
Showing 12 changed files with 67 additions and 11 deletions.
2 changes: 1 addition & 1 deletion poetry/masonry/builders/sdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def find_nearest_pkg(rel_path):
if from_top_level == ".":
continue

is_subpkg = "__init__.py" in filenames
is_subpkg = any([filename.endswith(".py") for filename in filenames])
if is_subpkg:
subpkg_paths.add(from_top_level)
parts = from_top_level.split(os.sep)
Expand Down
23 changes: 14 additions & 9 deletions poetry/masonry/utils/package_include.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ def __init__(self, base, include, formats=None, source=None):
base = base / source

super(PackageInclude, self).__init__(base, include, formats=formats)

self.check_elements()

@property
Expand All @@ -35,6 +34,8 @@ def refresh(self): # type: () -> PackageInclude
return self.check_elements()

def check_elements(self): # type: () -> PackageInclude
root = self._elements[0]

if not self._elements:
raise ValueError(
"{} does not contain any element".format(self._base / self._include)
Expand All @@ -44,20 +45,24 @@ def check_elements(self): # type: () -> PackageInclude
# Probably glob
self._is_package = True

# The __init__.py file should be first
root = self._elements[0]
if root.name != "__init__.py":
raise ValueError("{} is not a package.".format(root))
# Packages no longer need an __init__.py in python3, but there must
# at least be one .py file for it to be considered a package
if not any([element.suffix == ".py" for element in self._elements]):
raise ValueError("{} is not a package.".format(root.name))

self._package = root.parent.name
else:
if self._elements[0].is_dir():
if root.is_dir():
# If it's a directory, we include everything inside it
self._package = self._elements[0].name
self._elements = sorted(list(self._elements[0].glob("**/*")))
self._package = root.name
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
else:
self._package = self._elements[0].stem
self._package = root.stem
self._is_module = True

return self
Empty file.
1 change: 1 addition & 0 deletions tests/masonry/builders/test_complete.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ def test_complete_no_vcs():
"my_package/sub_pkg1/__init__.py",
"my_package/sub_pkg2/__init__.py",
"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/LICENSE",
"my_package-1.2.3.dist-info/WHEEL",
Expand Down
9 changes: 8 additions & 1 deletion tests/masonry/builders/test_sdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def test_make_setup():
"my_package",
"my_package.sub_pkg1",
"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["entry_points"] == {
Expand Down Expand Up @@ -178,6 +179,7 @@ def test_find_files_to_add():
Path("my_package/sub_pkg1/__init__.py"),
Path("my_package/sub_pkg2/__init__.py"),
Path("my_package/sub_pkg2/data2/data.json"),
Path("my_package/sub_pkg3/foo.py"),
Path("pyproject.toml"),
]
)
Expand Down Expand Up @@ -213,7 +215,12 @@ def test_find_packages():
pkg_dir, packages, pkg_data = builder.find_packages(include)

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 == {
"": ["*"],
"my_package": ["data1/*"],
Expand Down
Empty file added tests/masonry/utils/__init__.py
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
43 changes: 43 additions & 0 deletions tests/masonry/utils/test_package_include.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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."

0 comments on commit c401850

Please sign in to comment.