Skip to content

Commit 3442b70

Browse files
authored
[stubgenc] fixes and typos (#9877)
* [stubdoc] fix typo * [stubgenc] Add Callable to _DEFAULT_TYPING_IMPORTS * [stubgenc] Fix parsing signatures with empty argument list * [stubgenc] Replace NoneType with None * [stubgenc] Skip pybind11-specific internal attributes * [stubgenc] Test stub generation on pybind11-mypy-demo project
1 parent a540a1a commit 3442b70

File tree

6 files changed

+113
-10
lines changed

6 files changed

+113
-10
lines changed

.github/workflows/test_stubgenc.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Test stubgenc on pybind11-mypy-demo
2+
3+
on:
4+
push:
5+
branches: [master]
6+
tags: ['*']
7+
pull_request:
8+
paths:
9+
- 'misc/test-stubgenc.sh'
10+
- 'mypy/stubgenc.py'
11+
- 'mypy/stubdoc.py'
12+
- 'test-data/stubgen/**'
13+
14+
jobs:
15+
stubgenc:
16+
# Check stub file generation for a small pybind11 project
17+
# (full text match is required to pass)
18+
runs-on: ubuntu-latest
19+
steps:
20+
21+
- uses: actions/checkout@v2
22+
23+
- name: initialize submodules
24+
run: git submodule update --init
25+
26+
- name: Setup 🐍 3.8
27+
uses: actions/setup-python@v2
28+
with:
29+
python-version: 3.8
30+
31+
- name: Test stubgenc
32+
run: misc/test-stubgenc.sh

misc/test-stubgenc.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
# This script is expected to be run from root of the mypy repo
3+
4+
# Install dependencies, demo project and mypy
5+
python -m pip install -r test-requirements.txt
6+
python -m pip install pybind11-mypy-demo==0.0.1
7+
python -m pip install .
8+
9+
# Remove expected stubs and generate new inplace
10+
rm -rf test-data/stubgen/pybind11_mypy_demo
11+
stubgen -p pybind11_mypy_demo -o test-data/stubgen/
12+
13+
# Compare generated stubs to expected ones
14+
git diff --exit-code test-data/stubgen/pybind11_mypy_demo

mypy/stubdoc.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ def add_token(self, token: tokenize.TokenInfo) -> None:
140140
self.state.pop()
141141
elif self.state[-1] == STATE_ARGUMENT_LIST:
142142
self.arg_name = self.accumulator
143-
if not _ARG_NAME_RE.match(self.arg_name):
143+
if not (token.string == ')' and self.accumulator.strip() == '') \
144+
and not _ARG_NAME_RE.match(self.arg_name):
144145
# Invalid argument name.
145146
self.reset()
146147
return
@@ -235,7 +236,7 @@ def is_unique_args(sig: FunctionSig) -> bool:
235236
"""return true if function argument names are unique"""
236237
return len(sig.args) == len(set((arg.name for arg in sig.args)))
237238

238-
# Return only signatures that have unique argument names. Mypy fails on non-uniqnue arg names.
239+
# Return only signatures that have unique argument names. Mypy fails on non-unique arg names.
239240
return [sig for sig in sigs if is_unique_args(sig)]
240241

241242

mypy/stubgenc.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
infer_arg_sig_from_anon_docstring, infer_ret_type_sig_from_anon_docstring, FunctionSig
1818
)
1919

20-
2120
# Members of the typing module to consider for importing by default.
2221
_DEFAULT_TYPING_IMPORTS = (
2322
'Any',
23+
'Callable',
2424
'Dict',
2525
'Iterable',
2626
'Iterator',
@@ -231,6 +231,8 @@ def strip_or_import(typ: str, module: ModuleType, imports: List[str]) -> str:
231231
stripped_type = typ[len('builtins') + 1:]
232232
else:
233233
imports.append('import %s' % (arg_module,))
234+
if stripped_type == 'NoneType':
235+
stripped_type = 'None'
234236
return stripped_type
235237

236238

@@ -365,14 +367,20 @@ def method_name_sort_key(name: str) -> Tuple[int, str]:
365367
return 1, name
366368

367369

370+
def is_pybind_skipped_attribute(attr: str) -> bool:
371+
return attr.startswith("__pybind11_module_local_")
372+
373+
368374
def is_skipped_attribute(attr: str) -> bool:
369-
return attr in ('__getattribute__',
370-
'__str__',
371-
'__repr__',
372-
'__doc__',
373-
'__dict__',
374-
'__module__',
375-
'__weakref__') # For pickling
375+
return (attr in ('__getattribute__',
376+
'__str__',
377+
'__repr__',
378+
'__doc__',
379+
'__dict__',
380+
'__module__',
381+
'__weakref__') # For pickling
382+
or is_pybind_skipped_attribute(attr)
383+
)
376384

377385

378386
def infer_method_sig(name: str) -> List[ArgSig]:

test-data/stubgen/pybind11_mypy_demo/__init__.pyi

Whitespace-only changes.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
from typing import Any
2+
3+
from typing import overload
4+
PI: float
5+
6+
def answer() -> int: ...
7+
def midpoint(left: float, right: float) -> float: ...
8+
def sum(arg0: int, arg1: int) -> int: ...
9+
def weighted_midpoint(left: float, right: float, alpha: float = ...) -> float: ...
10+
11+
class Point:
12+
AngleUnit: Any = ...
13+
LengthUnit: Any = ...
14+
origin: Any = ...
15+
@overload
16+
def __init__(self) -> None: ...
17+
@overload
18+
def __init__(self, x: float, y: float) -> None: ...
19+
@overload
20+
def __init__(*args, **kwargs) -> Any: ...
21+
@overload
22+
def distance_to(self, x: float, y: float) -> float: ...
23+
@overload
24+
def distance_to(self, other: Point) -> float: ...
25+
@overload
26+
def distance_to(*args, **kwargs) -> Any: ...
27+
@property
28+
def angle_unit(self) -> pybind11_mypy_demo.basics.Point.AngleUnit: ...
29+
@angle_unit.setter
30+
def angle_unit(self, val: pybind11_mypy_demo.basics.Point.AngleUnit) -> None: ...
31+
@property
32+
def length(self) -> float: ...
33+
@property
34+
def length_unit(self) -> pybind11_mypy_demo.basics.Point.LengthUnit: ...
35+
@length_unit.setter
36+
def length_unit(self, val: pybind11_mypy_demo.basics.Point.LengthUnit) -> None: ...
37+
@property
38+
def x(self) -> float: ...
39+
@x.setter
40+
def x(self, val: float) -> None: ...
41+
@property
42+
def x_axis(self) -> pybind11_mypy_demo.basics.Point: ...
43+
@property
44+
def y(self) -> float: ...
45+
@y.setter
46+
def y(self, val: float) -> None: ...
47+
@property
48+
def y_axis(self) -> pybind11_mypy_demo.basics.Point: ...

0 commit comments

Comments
 (0)