Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6b3334d

Browse files
committed
Fix relative imports and improve private name handling
1 parent ffcbd34 commit 6b3334d

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

mypy/stubgen.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ def __init__(self,
484484

485485
def visit_mypy_file(self, o: MypyFile) -> None:
486486
self.module = o.fullname() # Current module being processed
487+
self.path = o.path
487488
self.defined_names = find_defined_names(o)
488489
self.referenced_names = find_referenced_names(o)
489490
typing_imports = ["Any", "Optional", "TypeVar"]
@@ -833,6 +834,14 @@ def visit_import_from(self, o: ImportFrom) -> None:
833834
exported_names = set() # type: Set[str]
834835
import_names = []
835836
module, relative = self.translate_module_name(o.id, o.relative)
837+
if self.module:
838+
full_module, ok = mypy.util.correct_relative_import(
839+
self.module, relative, module, self.path.endswith('.__init__.py')
840+
)
841+
if not ok:
842+
full_module = module
843+
else:
844+
full_module = module
836845
if module == '__future__':
837846
return # Not preserved
838847
for name, as_name in o.names:
@@ -842,18 +851,24 @@ def visit_import_from(self, o: ImportFrom) -> None:
842851
continue
843852
exported = False
844853
if as_name is None and self.module and (self.module + '.' + name) in EXTRA_EXPORTED:
854+
# Special case certain names that should be exported, against our general rules.
845855
exported = True
846-
if (as_name is None and name not in self.referenced_names and not self._all_
856+
is_private = self.is_private_name(name, full_module + '.' + name)
857+
if (as_name is None
858+
and name not in self.referenced_names
859+
and not self._all_
860+
and not is_private
847861
and module not in ('abc', 'typing', 'asyncio')):
848862
# An imported name that is never referenced in the module is assumed to be
849863
# exported, unless there is an explicit __all__. Note that we need to special
850864
# case 'abc' since some references are deleted during semantic analysis.
851865
exported = True
852-
top_level = module.split('.')[0]
866+
top_level = full_module.split('.')[0]
853867
if (as_name is None
854868
and not self.export_less
855869
and not self._all_
856870
and self.module
871+
and not is_private
857872
and top_level in (self.module.split('.')[0],
858873
'_' + self.module.split('.')[0])):
859874
# Export imports from the same package, since we can't reliably tell whether they

test-data/unit/stubgen.test

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,3 +1967,51 @@ c: C
19671967
# p/a.pyi
19681968
class A: ...
19691969
class B: ...
1970+
1971+
[case testExportInternalImportsByDefaultUsingRelativeImport]
1972+
# modules: p.a
1973+
1974+
[file p/__init__.py]
1975+
1976+
[file p/a.py]
1977+
from .b import f
1978+
f()
1979+
1980+
[file p/b.py]
1981+
def f(): pass
1982+
1983+
[out]
1984+
from .b import f as f
1985+
1986+
[case testExportInternalImportsByDefaultSkipPrivate]
1987+
# modules: p.a
1988+
1989+
[file p/__init__.py]
1990+
1991+
[file p/a.py]
1992+
from .b import _f, _g as _g
1993+
_f()
1994+
1995+
[file p/b.py]
1996+
def _f(): pass
1997+
def _g(): pass
1998+
x = 0
1999+
2000+
[out]
2001+
from .b import _f
2002+
2003+
[case testExportInternalImportsByDefaultIncludePrivate]
2004+
# flags: --include-private
2005+
# modules: p.a
2006+
2007+
[file p/__init__.py]
2008+
2009+
[file p/a.py]
2010+
from .b import _f
2011+
_f()
2012+
2013+
[file p/b.py]
2014+
def _f(): pass
2015+
2016+
[out]
2017+
from .b import _f as _f

0 commit comments

Comments
 (0)