@@ -33,6 +33,21 @@ def refresh(self): # type: () -> PackageInclude
33
33
34
34
return self .check_elements ()
35
35
36
+ def is_stub_only (self ): # type: () -> bool
37
+ # returns `True` if this a PEP 561 stub-only package,
38
+ # see [PEP 561](https://www.python.org/dev/peps/pep-0561/#stub-only-packages)
39
+ return self .package .endswith ("-stubs" ) and all (
40
+ el .suffix == ".pyi"
41
+ or (el .parent .name == self .package and el .name == "py.typed" )
42
+ for el in self .elements
43
+ if el .is_file ()
44
+ )
45
+
46
+ def has_modules (self ): # type: () -> bool
47
+ # Packages no longer need an __init__.py in python3, but there must
48
+ # at least be one .py file for it to be considered a package
49
+ return any (element .suffix == ".py" for element in self .elements )
50
+
36
51
def check_elements (self ): # type: () -> PackageInclude
37
52
if not self ._elements :
38
53
raise ValueError (
@@ -43,20 +58,18 @@ def check_elements(self): # type: () -> PackageInclude
43
58
if len (self ._elements ) > 1 :
44
59
# Probably glob
45
60
self ._is_package = True
61
+ self ._package = root .parent .name
46
62
47
- # Packages no longer need an __init__.py in python3, but there must
48
- # at least be one .py file for it to be considered a package
49
- if not any ([element .suffix == ".py" for element in self ._elements ]):
63
+ if not self .is_stub_only () and not self .has_modules ():
50
64
raise ValueError ("{} is not a package." .format (root .name ))
51
65
52
- self ._package = root .parent .name
53
66
else :
54
67
if root .is_dir ():
55
68
# If it's a directory, we include everything inside it
56
69
self ._package = root .name
57
70
self ._elements = sorted (list (root .glob ("**/*" )))
58
71
59
- if not any ([ element . suffix == ".py" for element in self ._elements ] ):
72
+ if not self . is_stub_only () and not self .has_modules ( ):
60
73
raise ValueError ("{} is not a package." .format (root .name ))
61
74
62
75
self ._is_package = True
0 commit comments