8000 Various improvements to stubgen by JukkaL · Pull Request #7921 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

Various improvements to stubgen #7921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 51 commits into from
Nov 14, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
aa0673f
Stubgen: Remove misplaced type comments before parsing
JukkaL Apr 11, 2019
ae33876
stubgen: Don't fail if docstring cannot be tokenized
JukkaL Apr 11, 2019
80108d3
stubgen: Handle None value for __file__
JukkaL Apr 12, 2019
37a1ab9
stubgen: Fix None-related crash
JukkaL Apr 12, 2019
020b11f
stubgen: Attempt to fix namespace packages
JukkaL Apr 12, 2019
e1de866
stubgen: Add --verbose and --quiet flags
JukkaL Apr 12, 2019
4473075
stubgen: Use __init__.pyi for C modules when needed
JukkaL Apr 12, 2019
3a0986d
stubgen: If we can't import a module, give more information
JukkaL Apr 12, 2019
049a2a4
stubgen: Work around crash
JukkaL Apr 12, 2019
bbf6268
stubgen: Don't fail if a class has a cyclic MRO
JukkaL Apr 12, 2019
a3ebf3c 8000
stubgen: Log runtime imports in verbose mode
JukkaL Apr 12, 2019
a3a35fe
stubgen: More verbose output
JukkaL Apr 12, 2019
e287301
stubgen: Skip certain special cased packages
JukkaL Apr 12, 2019
819a77d
stubgen: Filter out additional things that look like type comments
JukkaL Apr 12, 2019
02d4184
stubgen: Survive inconsistent MROs
JukkaL Apr 12, 2019
67142d6
stubgen: Remove message when there are only C modules
JukkaL Apr 12, 2019
bc3ca08
Fix rebase issue
JukkaL Nov 4, 2019
b1814d9
Fix after rebase
JukkaL Nov 4, 2019
6f4a1fe
Add missing stuff
JukkaL Nov 4, 2019
25e3258
Fix signatures generated by stubgen for various dunder C methods
JukkaL Apr 10, 2019
c9d2987
Add missing line
JukkaL Nov 4, 2019
8777b5f
Ignore unreachable code in stubgen to avoid crashes
JukkaL Apr 9, 2019
5ccd902
Fix C dunder method inference tests
JukkaL Nov 4, 2019
09f1b13
Preserve @abstractproperty in stubgen
JukkaL Apr 10, 2019
a9721ed
Stubgen: Avoid name clashes between typing.Any and class Any etc.
JukkaL Apr 10, 2019
6cefdc4
Stubgen: special case certain names to be exported
JukkaL Apr 10, 2019
95ab57c
Fix None errors
JukkaL Nov 4, 2019
156fe17
Add some docstrings and comments to stubgen tests
JukkaL Apr 10, 2019
9b802e3
Stubgen: Generate exports for imported names that aren't referenced
JukkaL Apr 10, 2019
d7b2942
Stubgen: allow special casing internal definitions to be exported
JukkaL Apr 10, 2019
b739314
Stubgen: translate imports from vendored six to use real six
JukkaL Apr 10, 2019
add4a64
Stubgen: Remove generated header
JukkaL Apr 10, 2019
8da487d
Add unit tests for skipping blacklisted and test modules
JukkaL May 10, 2019
376513d
Add docstring
JukkaL Nov 4, 2019
41a1f22
Add test case for vendored package
JukkaL Nov 4, 2019
b6db629
Fix lint
JukkaL Nov 11, 2019
c6aca1b
Update test case
JukkaL Nov 11, 2019
3309f74
Always filter out tests
JukkaL Nov 4, 2019
575cecd
Simplify redundant note
JukkaL Nov 4, 2019
bde23a1
Skip conftest modules (used for pytest tests)
JukkaL Nov 4, 2019
b4554e6
Fix crash
JukkaL Nov 5, 2019
c84677b
Filter out more kinds of bad function type comments
JukkaL Nov 5, 2019
be7414e
Recognize more modules as test modules
JukkaL Nov 5, 2019
07e1955
Revert changes to imports
JukkaL Nov 11, 2019
e6bac88
Try to fix Windows
JukkaL Nov 11, 2019
548bb10
Attempt to fix compiled
JukkaL Nov 11, 2019
f876154
Fix lint
JukkaL Nov 11, 2019
56d1a73
Try to fix Python 3.5
JukkaL Nov 11, 2019
58ae038
Respond to feedback
JukkaL Nov 14, 2019
2989121
Merge branch 'master' into stubgen-fixes-batch
JukkaL Nov 14, 2019
073832e
Fix stuff
JukkaL Nov 14, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Stubgen: Avoid name clashes between typing.Any and class Any etc.
Also support class named Optional.
  • Loading branch information
JukkaL committed Nov 11, 2019
commit a9721edea955b1f9f786ea9ad8c146dd3f910e59
54 changes: 48 additions & 6 deletions mypy/stubgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,33 @@ def import_lines(self) -> List[str]:
return result


def find_defined_names(file: MypyFile) -> Set[str]:
finder = DefinitionFinder()
file.accept(finder)
return finder.names


class DefinitionFinder(mypy.traverser.TraverserVisitor):
"""Find names of things defined at the top level of a module."""

# TODO: Assignment statements etc.

def __init__(self) -> None:
# Short names of things defined at the top level.
self.names = set() # type: Set[str]

def visit_class_def(self, o: ClassDef) -> None:
# Don't recurse into classes, as we only keep track of top-level definitions.
self.names.add(o.name)

def visit_func_def(self, o: FuncDef) -> None:
# Don't recurse, as we only keep track of top-level definitions.
self.names.add(o.name())


class StubGenerator(mypy.traverser.TraverserVisitor):
"""Generate stub text from a mypy AST."""

def __init__(self, _all_: Optional[List[str]], pyversion: Tuple[int, int],
include_private: bool = False, analyzed: bool = False) -> None:
# Best known value of __all__.
Expand All @@ -380,13 +406,20 @@ def __init__(self, _all_: Optional[List[str]], pyversion: Tuple[int, int],
self.analyzed = analyzed
# Add imports that could be implicitly generated
self.import_tracker.add_import_from("collections", [("namedtuple", None)])
typing_imports = "Any Optional TypeVar".split()
self.import_tracker.add_import_from("typing", [(t, None) for t in typing_imports])
# Names in __all__ are required
for name in _all_ or ():
self.import_tracker.reexport(name)
self.defined_names = set() # type: Set[str]

def visit_mypy_file(self, o: MypyFile) -> None:
self.defined_names = find_defined_names(o)
typing_imports = ["Any", "Optional", "TypeVar"]
for t in typing_imports:
if t not in self.defined_names:
alias = None
else:
alias = '_' + t
self.import_tracker.add_import_from("typing", [(t, alias)])
super().visit_mypy_file(o)
undefined_names = [name for name in self._all_ or []
if name not in self._toplevel_names]
Expand Down Expand Up @@ -434,7 +467,7 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False) -> None:
and not is_self_arg
and not is_cls_arg):
self.add_typing_import("Any")
annotation = ": Any"
annotation = ": {}".format(self.typing_name("Any"))
elif annotated_type and not is_self_arg:
annotation = ": {}".format(self.print_annotation(annotated_type))
else:
Expand Down Expand Up @@ -462,7 +495,7 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False) -> None:
retname = self.print_annotation(o.unanalyzed_type.ret_type)
elif isinstance(o, FuncDef) and o.is_abstract:
# Always assume abstract methods return Any unless explicitly annotated.
retname = 'Any'
retname = self.typing_name('Any')
self.add_typing_import("Any")
elif o.name() == '__init__' or not has_return_statement(o) and not is_abstract:
retname = 'None'
Expand Down Expand Up @@ -795,11 +828,19 @@ def add_decorator(self, name: str) -> None:
def clear_decorators(self) -> None:
self._decorators.clear()

def typing_name(self, name: str) -> str:
if name in self.defined_names:
# Avoid name clash between name from typing and a name defined in stub.
return '_' + name
else:
return name

def add_typing_import(self, name: str) -> None:
"""Add a name to be imported from typing, unless it's imported already.

The import will be internal to the stub.
"""
name = self.typing_name(name)
self.import_tracker.require_name(name)

def add_import_line(self, line: str) -> None:
Expand Down Expand Up @@ -867,9 +908,10 @@ def get_str_type_of_node(self, rvalue: Expression,
isinstance(rvalue, NameExpr) and rvalue.name == 'None':
self.add_typing_import('Optional')
self.add_typing_import('Any')
return 'Optional[Any]'
return '{}[{}]'.format(self.typing_name('Optional'),
self.typing_name('Any'))
self.add_typing_import('Any')
return 'Any'
return self.typing_name('Any')

def print_annotation(self, t: Type) -> str:
printer = AnnotationPrinter(self)
Expand Down
26 changes: 26 additions & 0 deletions test-data/unit/stubgen.test
Original file line number Diff line number Diff line change
Expand Up @@ -1606,3 +1606,29 @@ from typing import Any
class A(metaclass=abc.ABCMeta):
@abstractproperty
def x(self) -> Any: ...

[case testClassWithNameAnyOrOptional]
def f(x=object()):
return 1

def g(x=None): pass

x = g()

class Any:
pass

def Optional():
return 0

[out]
from typing import Any as _Any, Optional as _Optional

def f(x: _Any = ...): ...
def g(x: _Optional[_Any] = ...) -> None: ...

x: _Any

class Any: ...

def Optional(): ...
0