pyflyby 1.8.6__tar.gz → 1.8.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyflyby might be problematic. Click here for more details.
- {pyflyby-1.8.6/lib/python/pyflyby.egg-info → pyflyby-1.8.7}/PKG-INFO +2 -2
- {pyflyby-1.8.6 → pyflyby-1.8.7}/README.rst +1 -1
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_autoimp.py +7 -20
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_comms.py +15 -10
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_imports2s.py +44 -2
- {pyflyby-1.8.6/lib/python → pyflyby-1.8.7/bin}/pyflyby/_parse.py +25 -92
- {pyflyby-1.8.6/lib/python → pyflyby-1.8.7/bin}/pyflyby/_py.py +21 -36
- {pyflyby-1.8.6/lib/python → pyflyby-1.8.7/bin}/pyflyby/_version.py +1 -1
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/tidy-imports +10 -7
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_autoimp.py +7 -20
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_comms.py +15 -10
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_imports2s.py +44 -2
- {pyflyby-1.8.6/bin → pyflyby-1.8.7/lib/python}/pyflyby/_parse.py +25 -92
- {pyflyby-1.8.6/bin → pyflyby-1.8.7/lib/python}/pyflyby/_py.py +21 -36
- {pyflyby-1.8.6/bin → pyflyby-1.8.7/lib/python}/pyflyby/_version.py +1 -1
- {pyflyby-1.8.6 → pyflyby-1.8.7/lib/python/pyflyby.egg-info}/PKG-INFO +2 -2
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby.egg-info/requires.txt +1 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/setup.py +1 -1
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_autoimp.py +2 -25
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_cmdline.py +62 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_interactive.py +8 -10
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_parse.py +12 -24
- {pyflyby-1.8.6 → pyflyby-1.8.7}/.pyflyby +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/LICENSE.txt +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/MANIFEST.in +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/autoipython +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/autopython +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/collect-exports +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/collect-imports +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/create-imports +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/find-import +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/list-bad-xrefs +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/prune-broken-imports +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/__init__.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/__main__.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_cmdline.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_dbg.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_docxref.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_file.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_flags.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_format.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_idents.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_importclns.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_importdb.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_importstmt.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_interactive.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_livepatch.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_log.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_modules.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/_util.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/autoimport.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby/importdb.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/pyflyby-diff +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/reformat-imports +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/replace-star-imports +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/bin/transform-imports +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/LICENSE.txt +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/Makefile +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/TODO.txt +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/__init__.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/api.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/autoimp.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/cmdline.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/comms.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/dbg.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/file.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/flags.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/format.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/idents.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/importclns.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/importdb.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/imports2s.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/importstmt.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/interactive.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/livepatch.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/log.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/modules.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/parse.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/py.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/api/util.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/autoipython.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/cli.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/collect_exports.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/collect_imports.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/find_import.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/prune_broken_imports.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/py.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/pyflyby_diff.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/reformat_imports.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/replace_star_imports.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/tidy_imports.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/cli/transform_imports.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/conf.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/index.rst +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/make.bat +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/doc/testing.txt +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/etc/pyflyby/canonical.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/etc/pyflyby/common.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/etc/pyflyby/forget.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/etc/pyflyby/mandatory.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/etc/pyflyby/numpy.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/etc/pyflyby/std.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/emacs/pyflyby.el +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/__init__.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/__main__.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_cmdline.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_dbg.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_docxref.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_file.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_flags.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_format.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_idents.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_importclns.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_importdb.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_importstmt.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_interactive.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_livepatch.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_log.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_modules.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/_util.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/autoimport.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby/importdb.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby.egg-info/SOURCES.txt +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby.egg-info/dependency_links.txt +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby.egg-info/entry_points.txt +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/lib/python/pyflyby.egg-info/top_level.txt +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/libexec/pyflyby/colordiff +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/libexec/pyflyby/diff-colorize +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/setup.cfg +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/__init__.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_0testconfig.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_docxref.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_file.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_flags.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_format.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_idents.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_importclns.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_importdb.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_imports2s.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_importstmt.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_jupyterlab_pyflyby.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_livepatch.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_modules.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_py.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/test_util.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tests/xrefs.py +0 -0
- {pyflyby-1.8.6 → pyflyby-1.8.7}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyflyby
|
|
3
|
-
Version: 1.8.
|
|
3
|
+
Version: 1.8.7
|
|
4
4
|
Summary: pyflyby - Python development productivity tools, in particular automatic import management
|
|
5
5
|
Home-page: https://pypi.org/project/pyflyby/
|
|
6
6
|
Author: Karl Chen
|
|
@@ -257,7 +257,7 @@ Compatibility
|
|
|
257
257
|
-------------
|
|
258
258
|
|
|
259
259
|
Tested with:
|
|
260
|
-
- Python 3.
|
|
260
|
+
- Python 3.8, 3.9, 3.10
|
|
261
261
|
- IPython 0.10, 0.11, 0.12, 0.13, 1.0, 1.2, 2.0, 2.1, 2.2, 2.3, 2.4, 3.0,
|
|
262
262
|
3.1, 3.2, 4.0., 7.11 (latest)
|
|
263
263
|
- IPython (text console), IPython Notebook, Spyder
|
|
@@ -236,7 +236,7 @@ Compatibility
|
|
|
236
236
|
-------------
|
|
237
237
|
|
|
238
238
|
Tested with:
|
|
239
|
-
- Python 3.
|
|
239
|
+
- Python 3.8, 3.9, 3.10
|
|
240
240
|
- IPython 0.10, 0.11, 0.12, 0.13, 1.0, 1.2, 2.0, 2.1, 2.2, 2.3, 2.4, 3.0,
|
|
241
241
|
3.1, 3.2, 4.0., 7.11 (latest)
|
|
242
242
|
- IPython (text console), IPython Notebook, Spyder
|
|
@@ -609,17 +609,13 @@ class _MissingImportFinder(object):
|
|
|
609
609
|
# scope.
|
|
610
610
|
# - Store the name in the current scope (but not visibly to
|
|
611
611
|
# args/decorator_list).
|
|
612
|
-
|
|
613
|
-
assert node._fields == ('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment'), node._fields
|
|
614
|
-
else:
|
|
615
|
-
assert node._fields == ('name', 'args', 'body', 'decorator_list', 'returns'), node._fields
|
|
612
|
+
assert node._fields == ('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment'), node._fields
|
|
616
613
|
with self._NewScopeCtx(include_class_scopes=True):
|
|
617
614
|
self.visit(node.args)
|
|
618
615
|
self.visit(node.decorator_list)
|
|
619
616
|
if node.returns:
|
|
620
617
|
self.visit(node.returns)
|
|
621
|
-
|
|
622
|
-
self._visit_typecomment(node.type_comment)
|
|
618
|
+
self._visit_typecomment(node.type_comment)
|
|
623
619
|
old_in_FunctionDef = self._in_FunctionDef
|
|
624
620
|
self._in_FunctionDef = True
|
|
625
621
|
with self._NewScopeCtx(unhide_classdef=True):
|
|
@@ -671,10 +667,7 @@ class _MissingImportFinder(object):
|
|
|
671
667
|
self.visit(node)
|
|
672
668
|
|
|
673
669
|
def visit_arguments(self, node):
|
|
674
|
-
|
|
675
|
-
assert node._fields == ('posonlyargs', 'args', 'vararg', 'kwonlyargs', 'kw_defaults', 'kwarg', 'defaults'), node._fields
|
|
676
|
-
else:
|
|
677
|
-
assert node._fields == ('args', 'vararg', 'kwonlyargs', 'kw_defaults', 'kwarg', 'defaults'), node._fields
|
|
670
|
+
assert node._fields == ('posonlyargs', 'args', 'vararg', 'kwonlyargs', 'kw_defaults', 'kwarg', 'defaults'), node._fields
|
|
678
671
|
# Argument/parameter list. Note that the defaults should be
|
|
679
672
|
# considered "Load"s from the upper scope, and the argument names are
|
|
680
673
|
# "Store"s in the function scope.
|
|
@@ -693,8 +686,7 @@ class _MissingImportFinder(object):
|
|
|
693
686
|
# Store arg names.
|
|
694
687
|
self.visit(node.args)
|
|
695
688
|
self.visit(node.kwonlyargs)
|
|
696
|
-
|
|
697
|
-
self.visit(node.posonlyargs)
|
|
689
|
+
self.visit(node.posonlyargs)
|
|
698
690
|
# may be None.
|
|
699
691
|
if node.vararg:
|
|
700
692
|
self.visit(node.vararg)
|
|
@@ -807,16 +799,12 @@ class _MissingImportFinder(object):
|
|
|
807
799
|
self._visit_fullname(node.id, node.ctx)
|
|
808
800
|
|
|
809
801
|
def visit_arg(self, node):
|
|
810
|
-
|
|
811
|
-
assert node._fields == ('arg', 'annotation', 'type_comment'), node._fields
|
|
812
|
-
else:
|
|
813
|
-
assert node._fields == ('arg', 'annotation'), node._fields
|
|
802
|
+
assert node._fields == ('arg', 'annotation', 'type_comment'), node._fields
|
|
814
803
|
if node.annotation:
|
|
815
804
|
self.visit(node.annotation)
|
|
816
805
|
# Treat it like a Name node would from Python 2
|
|
817
806
|
self._visit_fullname(node.arg, ast.Param())
|
|
818
|
-
|
|
819
|
-
self._visit_typecomment(node.type_comment)
|
|
807
|
+
self._visit_typecomment(node.type_comment)
|
|
820
808
|
|
|
821
809
|
def visit_Attribute(self, node):
|
|
822
810
|
name_revparts = []
|
|
@@ -1512,8 +1500,7 @@ def find_missing_imports(arg, namespaces):
|
|
|
1512
1500
|
else:
|
|
1513
1501
|
return []
|
|
1514
1502
|
# Parse the string into an AST.
|
|
1515
|
-
|
|
1516
|
-
node = ast.parse(arg, **kw) # may raise SyntaxError
|
|
1503
|
+
node = ast.parse(arg, type_comments=True) # may raise SyntaxError
|
|
1517
1504
|
# Get missing imports from AST.
|
|
1518
1505
|
return _find_missing_imports_in_ast(node, namespaces)
|
|
1519
1506
|
elif isinstance(arg, PythonBlock):
|
|
@@ -121,24 +121,23 @@ def _reformat_helper(input_code, imports):
|
|
|
121
121
|
|
|
122
122
|
def extract_import_statements(text):
|
|
123
123
|
"""This is a util for notebook interactions and extracts import statements
|
|
124
|
-
from some python code.
|
|
125
|
-
|
|
124
|
+
from some python code. This function also re-orders imports.
|
|
126
125
|
Args:
|
|
127
126
|
code (str): The code from which import statements have to be extracted
|
|
128
127
|
|
|
129
128
|
Returns:
|
|
130
|
-
(
|
|
131
|
-
|
|
129
|
+
(str, str): The first returned value contains all the import statements.
|
|
130
|
+
The second returned value is the remaining code after
|
|
132
131
|
extracting the import statements.
|
|
133
132
|
"""
|
|
134
133
|
transformer = SourceToSourceFileImportsTransformation(text)
|
|
135
|
-
imports = [str(im.pretty_print()) for im in transformer.import_blocks]
|
|
134
|
+
imports = '\n'.join([str(im.pretty_print()) for im in transformer.import_blocks])
|
|
136
135
|
remaining_code = "\n".join([str(st.pretty_print()) if not isinstance(st, SourceToSourceImportBlockTransformation) else "" for st in transformer.blocks])
|
|
137
136
|
return imports, remaining_code
|
|
138
137
|
|
|
139
|
-
def collect_code_with_imports_on_top(imports, cell_array):
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
def collect_code_with_imports_on_top(imports: str, cell_array):
|
|
139
|
+
return (
|
|
140
|
+
imports
|
|
142
141
|
+ "\n"
|
|
143
142
|
+ "\n".join(
|
|
144
143
|
[
|
|
@@ -185,7 +184,13 @@ def comm_open_handler(comm, message):
|
|
|
185
184
|
elif data["type"] == TIDY_IMPORTS:
|
|
186
185
|
checksum = data.get("checksum", '')
|
|
187
186
|
cell_array = data.get("cellArray", [])
|
|
188
|
-
import_statements
|
|
187
|
+
# import_statements is a string because when
|
|
188
|
+
# SourceToSourceFileImportsTransformation is run on a piece of code
|
|
189
|
+
# it will club similar imports together and re-order the imports
|
|
190
|
+
# by making the imports a string, all the imports are processed
|
|
191
|
+
# together making sure tidy-imports has context on all the imports
|
|
192
|
+
# while clubbing similar imports and re-ordering them.
|
|
193
|
+
import_statements, processed_cell_array = "", []
|
|
189
194
|
for cell in cell_array:
|
|
190
195
|
text = cell.get("text")
|
|
191
196
|
cell_type = cell.get("type")
|
|
@@ -201,6 +206,6 @@ def comm_open_handler(comm, message):
|
|
|
201
206
|
"checksum": checksum,
|
|
202
207
|
"type": TIDY_IMPORTS,
|
|
203
208
|
"cells": processed_cell_array,
|
|
204
|
-
"imports":
|
|
209
|
+
"imports": import_statements,
|
|
205
210
|
}
|
|
206
211
|
)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# pyflyby/_imports2s.py.
|
|
2
2
|
# Copyright (C) 2011-2018 Karl Chen.
|
|
3
3
|
# License: MIT http://opensource.org/licenses/MIT
|
|
4
|
+
from collections import defaultdict
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
import isort
|
|
7
7
|
from pyflyby._autoimp import scan_for_import_issues
|
|
8
8
|
from pyflyby._file import FileText, Filename
|
|
9
9
|
from pyflyby._flags import CompilerFlags
|
|
@@ -534,6 +534,48 @@ def replace_star_imports(codeblock, params=None):
|
|
|
534
534
|
return transformer.output(params=params)
|
|
535
535
|
|
|
536
536
|
|
|
537
|
+
def sort_imports(codeblock):
|
|
538
|
+
"""
|
|
539
|
+
Sort imports for better grouping.
|
|
540
|
+
:param codeblock:
|
|
541
|
+
:return: codeblock
|
|
542
|
+
"""
|
|
543
|
+
sorted_imports = isort.code(
|
|
544
|
+
str(codeblock),
|
|
545
|
+
# To sort all the import in lexicographic order
|
|
546
|
+
force_sort_within_sections=True,
|
|
547
|
+
# This is done below
|
|
548
|
+
lines_between_sections=0,
|
|
549
|
+
lines_after_imports=1
|
|
550
|
+
)
|
|
551
|
+
# Step 1: Split the input string into a list of lines
|
|
552
|
+
lines = sorted_imports.split('\n')
|
|
553
|
+
|
|
554
|
+
# Step 2: Identify groups of imports and keep track of their line numbers
|
|
555
|
+
pkg_lines = defaultdict(list)
|
|
556
|
+
line_pkg_dict = {}
|
|
557
|
+
for i, line in enumerate(lines):
|
|
558
|
+
match = re.match(r'(from (\w+)|import (\w+))', line)
|
|
559
|
+
if match:
|
|
560
|
+
current_pkg = match.groups()[1:3]
|
|
561
|
+
current_pkg = current_pkg[0] if current_pkg[0] is not None else current_pkg[1]
|
|
562
|
+
pkg_lines[current_pkg].append(i)
|
|
563
|
+
line_pkg_dict[i] = current_pkg
|
|
564
|
+
|
|
565
|
+
# Step 3: Create the output list of lines with blank lines around groups with more than one import
|
|
566
|
+
output_lines = []
|
|
567
|
+
for i, line in enumerate(lines):
|
|
568
|
+
if i > 0 and line_pkg_dict.get(i) != line_pkg_dict.get(i-1) and len(pkg_lines[line_pkg_dict.get(i)]) > 1:
|
|
569
|
+
output_lines.append('')
|
|
570
|
+
output_lines.append(line)
|
|
571
|
+
if i < len(lines) - 1 and line_pkg_dict.get(i) != line_pkg_dict.get(i+1) and len(pkg_lines[line_pkg_dict.get(i)]) > 1:
|
|
572
|
+
output_lines.append('')
|
|
573
|
+
|
|
574
|
+
# Step 4: Join the lines to create the output string
|
|
575
|
+
sorted_output_str = '\n'.join(output_lines)
|
|
576
|
+
return PythonBlock(sorted_output_str)
|
|
577
|
+
|
|
578
|
+
|
|
537
579
|
def transform_imports(codeblock, transformations, params=None):
|
|
538
580
|
"""
|
|
539
581
|
Transform imports as specified by ``transformations``.
|
|
@@ -24,19 +24,7 @@ from pyflyby._util import cached_attribute, cmp
|
|
|
24
24
|
|
|
25
25
|
from ast import Bytes
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
from ast import TypeIgnore, AsyncFunctionDef
|
|
29
|
-
else:
|
|
30
|
-
|
|
31
|
-
# TypeIgnore, AsyncFunctionDef does not exist on Python 3.7 and before. thus
|
|
32
|
-
# we define a dummy TypeIgnore, AsyncFunctionDef just to simplify remaining
|
|
33
|
-
# code.
|
|
34
|
-
|
|
35
|
-
class TypeIgnore:
|
|
36
|
-
pass
|
|
37
|
-
|
|
38
|
-
class AsyncFunctionDef:
|
|
39
|
-
pass
|
|
27
|
+
from ast import TypeIgnore, AsyncFunctionDef
|
|
40
28
|
|
|
41
29
|
|
|
42
30
|
def _is_comment_or_blank(line):
|
|
@@ -104,37 +92,27 @@ def _iter_child_nodes_in_order_internal_1(node):
|
|
|
104
92
|
assert node._fields == ("keys", "values")
|
|
105
93
|
yield list(zip(node.keys, node.values))
|
|
106
94
|
elif isinstance(node, (ast.FunctionDef, AsyncFunctionDef)):
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
yield res
|
|
124
|
-
else:
|
|
125
|
-
assert node._fields == ('name', 'args', 'body', 'decorator_list',
|
|
126
|
-
'returns'), node._fields
|
|
127
|
-
yield node.decorator_list, node.args, node.returns, node.body
|
|
95
|
+
assert node._fields == (
|
|
96
|
+
"name",
|
|
97
|
+
"args",
|
|
98
|
+
"body",
|
|
99
|
+
"decorator_list",
|
|
100
|
+
"returns",
|
|
101
|
+
"type_comment",
|
|
102
|
+
), node._fields
|
|
103
|
+
res = (
|
|
104
|
+
node.type_comment,
|
|
105
|
+
node.decorator_list,
|
|
106
|
+
node.args,
|
|
107
|
+
node.returns,
|
|
108
|
+
node.body,
|
|
109
|
+
)
|
|
110
|
+
yield res
|
|
128
111
|
# node.name is a string, not an AST node
|
|
129
112
|
elif isinstance(node, ast.arguments):
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
args = node.posonlyargs + node.args
|
|
134
|
-
else:
|
|
135
|
-
assert node._fields == ('args', 'vararg', 'kwonlyargs',
|
|
136
|
-
'kw_defaults', 'kwarg', 'defaults'), node._fields
|
|
137
|
-
args = node.args
|
|
113
|
+
assert node._fields == ('posonlyargs', 'args', 'vararg', 'kwonlyargs',
|
|
114
|
+
'kw_defaults', 'kwarg', 'defaults'), node._fields
|
|
115
|
+
args = node.posonlyargs + node.args
|
|
138
116
|
defaults = node.defaults or ()
|
|
139
117
|
num_no_default = len(args) - len(defaults)
|
|
140
118
|
yield args[:num_no_default]
|
|
@@ -187,22 +165,10 @@ def _flags_to_try(source, flags, auto_flags, mode):
|
|
|
187
165
|
If ``auto_flags`` is True, then yield ``flags`` and ``flags ^ print_function``.
|
|
188
166
|
"""
|
|
189
167
|
flags = CompilerFlags(flags)
|
|
190
|
-
if
|
|
191
|
-
|
|
192
|
-
flags = flags | CompilerFlags('type_comments')
|
|
193
|
-
yield flags
|
|
194
|
-
return
|
|
195
|
-
if not auto_flags:
|
|
196
|
-
yield flags
|
|
197
|
-
return
|
|
198
|
-
if mode == "eval":
|
|
199
|
-
if re.search(r"\bprint\b", source):
|
|
200
|
-
flags = flags | CompilerFlags("print_function")
|
|
201
|
-
yield flags
|
|
202
|
-
return
|
|
168
|
+
if re.search(r"# *type:", source):
|
|
169
|
+
flags = flags | CompilerFlags('type_comments')
|
|
203
170
|
yield flags
|
|
204
|
-
|
|
205
|
-
yield flags ^ CompilerFlags("print_function")
|
|
171
|
+
return
|
|
206
172
|
|
|
207
173
|
|
|
208
174
|
def _parse_ast_nodes(text, flags, auto_flags, mode):
|
|
@@ -348,14 +314,6 @@ def _annotate_ast_startpos(ast_node, parent_ast_node, minpos, text, flags):
|
|
|
348
314
|
"""
|
|
349
315
|
assert isinstance(ast_node, (ast.AST, str, TypeIgnore)), ast_node
|
|
350
316
|
|
|
351
|
-
# joined strings and children do not carry a column offset on pre-3.8
|
|
352
|
-
# this prevent reformatting.
|
|
353
|
-
# set the column offset to the parent value before 3.8
|
|
354
|
-
if (3, 7) < sys.version_info < (3, 8):
|
|
355
|
-
instances = (getattr(ast, "JoinedStr", None), ast.FormattedValue)
|
|
356
|
-
if ((isinstance(ast_node, instances) or isinstance(parent_ast_node, instances)) and ast_node.col_offset == -1) or isinstance(ast_node, ast.keyword):
|
|
357
|
-
ast_node.col_offset = parent_ast_node.col_offset
|
|
358
|
-
|
|
359
317
|
# First, traverse child nodes. If the first child node (recursively) is a
|
|
360
318
|
# multiline string, then we need to transfer its information to this node.
|
|
361
319
|
# Walk all nodes/fields of the AST. We implement this as a custom
|
|
@@ -400,9 +358,8 @@ def _annotate_ast_startpos(ast_node, parent_ast_node, minpos, text, flags):
|
|
|
400
358
|
if ast_node.col_offset >= 0:
|
|
401
359
|
# In Python 3.8+, FunctionDef.lineno is the line with the def. To
|
|
402
360
|
# account for decorators, we need the lineno of the first decorator
|
|
403
|
-
if (
|
|
404
|
-
|
|
405
|
-
and ast_node.decorator_list):
|
|
361
|
+
if (isinstance(ast_node, (ast.FunctionDef, ast.ClassDef, AsyncFunctionDef))
|
|
362
|
+
and ast_node.decorator_list):
|
|
406
363
|
delta = (ast_node.decorator_list[0].lineno-1,
|
|
407
364
|
# The col_offset doesn't include the @
|
|
408
365
|
ast_node.decorator_list[0].col_offset - 1)
|
|
@@ -486,9 +443,6 @@ def _annotate_ast_startpos(ast_node, parent_ast_node, minpos, text, flags):
|
|
|
486
443
|
for _m in re.finditer("[bBrRuU]*[\"\']", start_line)])
|
|
487
444
|
target_str = ast_node.s
|
|
488
445
|
|
|
489
|
-
if isinstance(target_str, bytes) and sys.version_info[:2] == (3, 7):
|
|
490
|
-
target_str = target_str.decode()
|
|
491
|
-
|
|
492
446
|
# Loop over possible end_linenos. The first one we've identified is the
|
|
493
447
|
# by far most likely one, but in theory it could be anywhere later in the
|
|
494
448
|
# file. This could be because of a dastardly concatenated string like
|
|
@@ -553,18 +507,8 @@ def _annotate_ast_startpos(ast_node, parent_ast_node, minpos, text, flags):
|
|
|
553
507
|
candidate_str = _test_parse_string_literal(subtext, flags)
|
|
554
508
|
if candidate_str is None:
|
|
555
509
|
continue
|
|
556
|
-
if isinstance(candidate_str, bytes) and sys.version_info[:2] == (3, 7):
|
|
557
|
-
candidate_str = candidate_str.decode()
|
|
558
510
|
|
|
559
511
|
maybe_fstring = False
|
|
560
|
-
try:
|
|
561
|
-
if (3, 7) <= sys.version_info <= (3, 8):
|
|
562
|
-
potential_start = text.lines[startpos.lineno - 1]
|
|
563
|
-
maybe_fstring = ("f'" in potential_start) or (
|
|
564
|
-
'f"' in potential_start
|
|
565
|
-
)
|
|
566
|
-
except IndexError:
|
|
567
|
-
pass
|
|
568
512
|
|
|
569
513
|
if target_str == candidate_str and target_str:
|
|
570
514
|
# Success!
|
|
@@ -589,17 +533,6 @@ def _annotate_ast_startpos(ast_node, parent_ast_node, minpos, text, flags):
|
|
|
589
533
|
for (sq, sp) in startpos_candidates
|
|
590
534
|
if sp in matched_prefix
|
|
591
535
|
]
|
|
592
|
-
if (3, 7) <= sys.version_info <= (3, 8):
|
|
593
|
-
if len(f_string_candidate_prefixes) == 1:
|
|
594
|
-
# we did not find the string but there is one fstring candidate starting it
|
|
595
|
-
|
|
596
|
-
ast_node.startpos, ast_node.endpos = f_string_candidate_prefixes[0]
|
|
597
|
-
return True
|
|
598
|
-
elif isinstance(parent_ast_node, ast.JoinedStr):
|
|
599
|
-
self_pos = parent_ast_node.values.index(ast_node)
|
|
600
|
-
ast_node.startpos = parent_ast_node.values[self_pos - 1].startpos
|
|
601
|
-
ast_node.endpos = parent_ast_node.values[self_pos - 1].endpos
|
|
602
|
-
return True
|
|
603
536
|
raise ValueError("Couldn't find exact position of %s" % (ast.dump(ast_node)))
|
|
604
537
|
|
|
605
538
|
|
|
@@ -379,10 +379,7 @@ FLAGS = CompilerFlags(["absolute_import", "with_statement", "division",
|
|
|
379
379
|
|
|
380
380
|
|
|
381
381
|
def _get_argspec(arg, _recurse=False):
|
|
382
|
-
|
|
383
|
-
from inspect import getfullargspec as getargspec, FullArgSpec as ArgSpec
|
|
384
|
-
else:
|
|
385
|
-
from inspect import getargspec, ArgSpec
|
|
382
|
+
from inspect import getfullargspec as getargspec, FullArgSpec as ArgSpec
|
|
386
383
|
if isinstance(arg, FunctionType):
|
|
387
384
|
return getargspec(arg)
|
|
388
385
|
elif isinstance(arg, MethodType):
|
|
@@ -402,10 +399,7 @@ def _get_argspec(arg, _recurse=False):
|
|
|
402
399
|
return _get_argspec(arg.__call__, _recurse=False)
|
|
403
400
|
elif callable(arg):
|
|
404
401
|
# Unknown, probably a built-in method.
|
|
405
|
-
|
|
406
|
-
return ArgSpec((), "args", "kwargs", None, [], None, {})
|
|
407
|
-
else:
|
|
408
|
-
return ArgSpec((), "args", "kwargs", None)
|
|
402
|
+
return ArgSpec((), "args", "kwargs", None, [], None, {})
|
|
409
403
|
raise TypeError(
|
|
410
404
|
"_get_argspec: unexpected %s" % (type(arg).__name__,))
|
|
411
405
|
|
|
@@ -515,12 +509,11 @@ def _build_function_usage_string(function_name, argspec, prefix):
|
|
|
515
509
|
if argspec.varargs:
|
|
516
510
|
syntax1 += " %s..." % argspec.varargs
|
|
517
511
|
syntax1 += "]" * len(defaults)
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
syntax1 += " --%s=..." % (arg,)
|
|
512
|
+
for arg in argspec.kwonlyargs:
|
|
513
|
+
if argspec.kwonlydefaults and arg in argspec.kwonlydefaults:
|
|
514
|
+
syntax1 += " [--%s=...]" % (arg,)
|
|
515
|
+
else:
|
|
516
|
+
syntax1 += " --%s=..." % (arg,)
|
|
524
517
|
if keywords:
|
|
525
518
|
syntax1 += " [--...]"
|
|
526
519
|
usage.append(syntax1)
|
|
@@ -531,12 +524,11 @@ def _build_function_usage_string(function_name, argspec, prefix):
|
|
|
531
524
|
syntax2 += " [--%s=...]" % (arg,)
|
|
532
525
|
else:
|
|
533
526
|
syntax2 += " --%s=..." % (arg,)
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
syntax2 += " --%s=..." % (arg,)
|
|
527
|
+
for arg in argspec.kwonlyargs:
|
|
528
|
+
if argspec.kwonlydefaults and arg in argspec.kwonlydefaults:
|
|
529
|
+
syntax2 += " [--%s=...]" % (arg,)
|
|
530
|
+
else:
|
|
531
|
+
syntax2 += " --%s=..." % (arg,)
|
|
540
532
|
if argspec.varargs:
|
|
541
533
|
syntax2 += " %s..." % argspec.varargs
|
|
542
534
|
if keywords:
|
|
@@ -717,20 +709,18 @@ def _parse_auto_apply_args(argspec, commandline_args, namespace, arg_mode="auto"
|
|
|
717
709
|
for argname, default in zip(argspec.args[len(argspec.args)-len(defaults):],
|
|
718
710
|
defaults):
|
|
719
711
|
argname2default[argname] = make_expr(default, "raw_value")
|
|
720
|
-
if
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
argname2default[argname] = make_expr(default, "raw_value")
|
|
712
|
+
if argspec.kwonlydefaults:
|
|
713
|
+
for argname, default in argspec.kwonlydefaults.items():
|
|
714
|
+
argname2default[argname] = make_expr(default, "raw_value")
|
|
724
715
|
# Create a map from prefix to arguments with that prefix. E.g. {"foo":
|
|
725
716
|
# ["foobar", "foobaz"]}
|
|
726
717
|
prefix2argname = {}
|
|
727
718
|
for argname in argspec.args:
|
|
728
719
|
for prefix in prefixes(argname):
|
|
729
720
|
prefix2argname.setdefault(prefix, []).append(argname)
|
|
730
|
-
|
|
731
|
-
for
|
|
732
|
-
|
|
733
|
-
prefix2argname.setdefault(prefix, []).append(argname)
|
|
721
|
+
for argname in argspec.kwonlyargs:
|
|
722
|
+
for prefix in prefixes(argname):
|
|
723
|
+
prefix2argname.setdefault(prefix, []).append(argname)
|
|
734
724
|
# Enumerate over input arguments.
|
|
735
725
|
got_pos_args = []
|
|
736
726
|
got_keyword_args = {}
|
|
@@ -769,14 +759,9 @@ def _parse_auto_apply_args(argspec, commandline_args, namespace, arg_mode="auto"
|
|
|
769
759
|
raise _ParseInterruptedWantHelp
|
|
770
760
|
if argname in ["source"]:
|
|
771
761
|
raise _ParseInterruptedWantSource
|
|
772
|
-
if
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
(argname,))
|
|
776
|
-
else:
|
|
777
|
-
if not argspec.keywords:
|
|
778
|
-
raise ParseError("Unknown option name %s" %
|
|
779
|
-
(argname,))
|
|
762
|
+
if not argspec.varkw:
|
|
763
|
+
raise ParseError("Unknown option name %s" %
|
|
764
|
+
(argname,))
|
|
780
765
|
|
|
781
766
|
elif len(matched_argnames) > 1:
|
|
782
767
|
raise ParseError(
|
|
@@ -27,10 +27,10 @@ import sys
|
|
|
27
27
|
import os
|
|
28
28
|
|
|
29
29
|
from pyflyby._cmdline import hfmt, parse_args, process_actions
|
|
30
|
-
from
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
from pyflyby._imports2s import (canonicalize_imports,
|
|
31
|
+
fix_unused_and_missing_imports,
|
|
32
|
+
replace_star_imports,
|
|
33
|
+
transform_imports, sort_imports)
|
|
34
34
|
from pyflyby._log import logger
|
|
35
35
|
|
|
36
36
|
import toml
|
|
@@ -145,20 +145,23 @@ def main():
|
|
|
145
145
|
parser.set_defaults(**default_config)
|
|
146
146
|
options, args = parse_args(
|
|
147
147
|
_add_opts_and_defaults, import_format_params=True, modify_action_params=True, defaults=default_config)
|
|
148
|
+
|
|
148
149
|
def modify(x):
|
|
149
|
-
if options.canonicalize:
|
|
150
|
-
x = canonicalize_imports(x, params=options.params)
|
|
151
150
|
if options.transformations:
|
|
152
151
|
x = transform_imports(x, options.transformations,
|
|
153
152
|
params=options.params)
|
|
154
153
|
if options.replace_star_imports:
|
|
155
154
|
x = replace_star_imports(x, params=options.params)
|
|
156
|
-
|
|
155
|
+
x = fix_unused_and_missing_imports(
|
|
157
156
|
x, params=options.params,
|
|
158
157
|
add_missing=options.add_missing,
|
|
159
158
|
remove_unused=options.remove_unused,
|
|
160
159
|
add_mandatory=options.add_mandatory,
|
|
161
160
|
)
|
|
161
|
+
sorted_imports = sort_imports(x)
|
|
162
|
+
if options.canonicalize:
|
|
163
|
+
sorted_imports = canonicalize_imports(sorted_imports, params=options.params)
|
|
164
|
+
return sorted_imports
|
|
162
165
|
process_actions(args, options.actions, modify)
|
|
163
166
|
|
|
164
167
|
|
|
@@ -609,17 +609,13 @@ class _MissingImportFinder(object):
|
|
|
609
609
|
# scope.
|
|
610
610
|
# - Store the name in the current scope (but not visibly to
|
|
611
611
|
# args/decorator_list).
|
|
612
|
-
|
|
613
|
-
assert node._fields == ('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment'), node._fields
|
|
614
|
-
else:
|
|
615
|
-
assert node._fields == ('name', 'args', 'body', 'decorator_list', 'returns'), node._fields
|
|
612
|
+
assert node._fields == ('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment'), node._fields
|
|
616
613
|
with self._NewScopeCtx(include_class_scopes=True):
|
|
617
614
|
self.visit(node.args)
|
|
618
615
|
self.visit(node.decorator_list)
|
|
619
616
|
if node.returns:
|
|
620
617
|
self.visit(node.returns)
|
|
621
|
-
|
|
622
|
-
self._visit_typecomment(node.type_comment)
|
|
618
|
+
self._visit_typecomment(node.type_comment)
|
|
623
619
|
old_in_FunctionDef = self._in_FunctionDef
|
|
624
620
|
self._in_FunctionDef = True
|
|
625
621
|
with self._NewScopeCtx(unhide_classdef=True):
|
|
@@ -671,10 +667,7 @@ class _MissingImportFinder(object):
|
|
|
671
667
|
self.visit(node)
|
|
672
668
|
|
|
673
669
|
def visit_arguments(self, node):
|
|
674
|
-
|
|
675
|
-
assert node._fields == ('posonlyargs', 'args', 'vararg', 'kwonlyargs', 'kw_defaults', 'kwarg', 'defaults'), node._fields
|
|
676
|
-
else:
|
|
677
|
-
assert node._fields == ('args', 'vararg', 'kwonlyargs', 'kw_defaults', 'kwarg', 'defaults'), node._fields
|
|
670
|
+
assert node._fields == ('posonlyargs', 'args', 'vararg', 'kwonlyargs', 'kw_defaults', 'kwarg', 'defaults'), node._fields
|
|
678
671
|
# Argument/parameter list. Note that the defaults should be
|
|
679
672
|
# considered "Load"s from the upper scope, and the argument names are
|
|
680
673
|
# "Store"s in the function scope.
|
|
@@ -693,8 +686,7 @@ class _MissingImportFinder(object):
|
|
|
693
686
|
# Store arg names.
|
|
694
687
|
self.visit(node.args)
|
|
695
688
|
self.visit(node.kwonlyargs)
|
|
696
|
-
|
|
697
|
-
self.visit(node.posonlyargs)
|
|
689
|
+
self.visit(node.posonlyargs)
|
|
698
690
|
# may be None.
|
|
699
691
|
if node.vararg:
|
|
700
692
|
self.visit(node.vararg)
|
|
@@ -807,16 +799,12 @@ class _MissingImportFinder(object):
|
|
|
807
799
|
self._visit_fullname(node.id, node.ctx)
|
|
808
800
|
|
|
809
801
|
def visit_arg(self, node):
|
|
810
|
-
|
|
811
|
-
assert node._fields == ('arg', 'annotation', 'type_comment'), node._fields
|
|
812
|
-
else:
|
|
813
|
-
assert node._fields == ('arg', 'annotation'), node._fields
|
|
802
|
+
assert node._fields == ('arg', 'annotation', 'type_comment'), node._fields
|
|
814
803
|
if node.annotation:
|
|
815
804
|
self.visit(node.annotation)
|
|
816
805
|
# Treat it like a Name node would from Python 2
|
|
817
806
|
self._visit_fullname(node.arg, ast.Param())
|
|
818
|
-
|
|
819
|
-
self._visit_typecomment(node.type_comment)
|
|
807
|
+
self._visit_typecomment(node.type_comment)
|
|
820
808
|
|
|
821
809
|
def visit_Attribute(self, node):
|
|
822
810
|
name_revparts = []
|
|
@@ -1512,8 +1500,7 @@ def find_missing_imports(arg, namespaces):
|
|
|
1512
1500
|
else:
|
|
1513
1501
|
return []
|
|
1514
1502
|
# Parse the string into an AST.
|
|
1515
|
-
|
|
1516
|
-
node = ast.parse(arg, **kw) # may raise SyntaxError
|
|
1503
|
+
node = ast.parse(arg, type_comments=True) # may raise SyntaxError
|
|
1517
1504
|
# Get missing imports from AST.
|
|
1518
1505
|
return _find_missing_imports_in_ast(node, namespaces)
|
|
1519
1506
|
elif isinstance(arg, PythonBlock):
|