Commit 9a283965 by Oleg Höfling Committed by GitHub

Fix regression in stub-only package (PEP-561) support

Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
parent dbc1e1b9
......@@ -33,6 +33,21 @@ class PackageInclude(Include):
return self.check_elements()
def is_stub_only(self): # type: () -> bool
# returns `True` if this a PEP 561 stub-only package,
# see [PEP 561](https://www.python.org/dev/peps/pep-0561/#stub-only-packages)
return self.package.endswith("-stubs") and all(
el.suffix == ".pyi"
or (el.parent.name == self.package and el.name == "py.typed")
for el in self.elements
if el.is_file()
)
def has_modules(self): # type: () -> bool
# 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
return any(element.suffix == ".py" for element in self.elements)
def check_elements(self): # type: () -> PackageInclude
if not self._elements:
raise ValueError(
......@@ -43,20 +58,18 @@ class PackageInclude(Include):
if len(self._elements) > 1:
# Probably glob
self._is_package = True
self._package = root.parent.name
# 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]):
if not self.is_stub_only() and not self.has_modules():
raise ValueError("{} is not a package.".format(root.name))
self._package = root.parent.name
else:
if root.is_dir():
# If it's a directory, we include everything inside it
self._package = root.name
self._elements = sorted(list(root.glob("**/*")))
if not any([element.suffix == ".py" for element in self._elements]):
if not self.is_stub_only() and not self.has_modules():
raise ValueError("{} is not a package.".format(root.name))
self._is_package = True
......
"""Example module"""
from typing import Tuple
version_info = Tuple[int, int, int]
[tool.poetry]
name = "pep-561-stubs"
version = "0.1"
description = "PEP 561 stub package example"
authors = [
"Oleg Höfling <oleg.hoefling@gmail.com>"
]
license = "MIT"
packages = [
{include = "pkg-stubs"}
]
[tool.poetry.dependencies]
python = "^3.6"
"""Example module"""
from typing import Tuple
version_info = Tuple[int, int, int]
[tool.poetry]
name = "pep-561-stubs"
version = "0.1"
description = "PEP 561 stub package example with the py.typed marker file"
authors = [
"Oleg Höfling <oleg.hoefling@gmail.com>"
]
license = "MIT"
packages = [
{include = "pkg-stubs"}
]
[tool.poetry.dependencies]
python = "^3.6"
[tool.poetry]
name = "pep-561-stubs"
version = "0.1"
description = "PEP 561 stub package example with an src layout"
authors = [
"Oleg Höfling <oleg.hoefling@gmail.com>"
]
license = "MIT"
packages = [
{include = "pkg-stubs", from = "src"}
]
[tool.poetry.dependencies]
python = "^3.6"
"""Example module"""
from typing import Tuple
version_info = Tuple[int, int, int]
......@@ -488,3 +488,21 @@ def test_excluded_subpackage():
exec(compile(setup_ast, filename="setup.py", mode="exec"), ns)
assert ns["packages"] == ["example"]
def test_sdist_package_pep_561_stub_only():
root = fixtures_dir / "pep_561_stub_only"
poetry = Factory().create_poetry(root)
builder = SdistBuilder(poetry, NullEnv(), NullIO())
builder.build()
sdist = root / "dist" / "pep-561-stubs-0.1.tar.gz"
assert sdist.exists()
with tarfile.open(str(sdist), "r") as tar:
names = tar.getnames()
assert "pep-561-stubs-0.1/pkg-stubs/__init__.pyi" in names
assert "pep-561-stubs-0.1/pkg-stubs/module.pyi" in names
assert "pep-561-stubs-0.1/pkg-stubs/subpkg/__init__.pyi" in names
......@@ -162,3 +162,33 @@ def test_dist_info_file_permissions():
z.getinfo("my_package-1.2.3.dist-info/entry_points.txt").external_attr
== 0o644 << 16
)
@pytest.mark.parametrize(
"package",
["pep_561_stub_only", "pep_561_stub_only_partial", "pep_561_stub_only_src"],
)
def test_wheel_package_pep_561_stub_only(package):
root = fixtures_dir / package
WheelBuilder.make(Factory().create_poetry(root), NullEnv(), NullIO())
whl = root / "dist" / "pep_561_stubs-0.1-py3-none-any.whl"
assert whl.exists()
with zipfile.ZipFile(str(whl)) as z:
assert "pkg-stubs/__init__.pyi" in z.namelist()
assert "pkg-stubs/module.pyi" in z.namelist()
assert "pkg-stubs/subpkg/__init__.pyi" in z.namelist()
def test_wheel_package_pep_561_stub_only_includes_typed_marker():
root = fixtures_dir / "pep_561_stub_only_partial"
WheelBuilder.make(Factory().create_poetry(root), NullEnv(), NullIO())
whl = root / "dist" / "pep_561_stubs-0.1-py3-none-any.whl"
assert whl.exists()
with zipfile.ZipFile(str(whl)) as z:
assert "pkg-stubs/py.typed" in z.namelist()
"""Example module"""
from typing import Tuple
version_info = Tuple[int, int, int]
"""Example module"""
from typing import Tuple
version_info = Tuple[int, int, int]
......@@ -50,3 +50,20 @@ def test_package_include_with_non_existent_directory():
err_str = str(with_includes / "not_a_dir") + " does not contain any element"
assert str(e.value) == err_str
def test_pep_561_stub_only_package_good_name_suffix():
pkg_include = PackageInclude(
base=fixtures_dir / "pep_561_stub_only", include="good-stubs"
)
assert pkg_include.elements == [
fixtures_dir / "pep_561_stub_only/good-stubs/__init__.pyi",
fixtures_dir / "pep_561_stub_only/good-stubs/module.pyi",
]
def test_pep_561_stub_only_package_bad_name_suffix():
with pytest.raises(ValueError) as e:
PackageInclude(base=fixtures_dir / "pep_561_stub_only", include="bad")
assert str(e.value) == "bad 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