pyflyby 1.8.9__tar.gz → 1.9.1__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.9/lib/python/pyflyby.egg-info → pyflyby-1.9.1}/PKG-INFO +1 -1
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/_autoimp.py +59 -20
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/_comms.py +21 -12
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/_dbg.py +8 -9
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_docxref.py +2 -3
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/_file.py +5 -8
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_flags.py +9 -5
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_format.py +5 -6
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_idents.py +10 -10
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_importclns.py +15 -16
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_importdb.py +5 -5
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_imports2s.py +1 -0
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_importstmt.py +37 -26
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/_interactive.py +22 -3
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/_livepatch.py +4 -4
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_modules.py +16 -13
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_parse.py +41 -14
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_py.py +36 -30
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/_util.py +23 -46
- {pyflyby-1.8.9/lib/python → pyflyby-1.9.1/bin}/pyflyby/_version.py +1 -1
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/tidy-imports +8 -3
- {pyflyby-1.8.9 → pyflyby-1.9.1}/etc/pyflyby/std.py +1 -1
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/_autoimp.py +59 -20
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/_comms.py +21 -12
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/_dbg.py +8 -9
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_docxref.py +2 -3
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/_file.py +5 -8
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_flags.py +9 -5
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_format.py +5 -6
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_idents.py +10 -10
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_importclns.py +15 -16
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_importdb.py +5 -5
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_imports2s.py +1 -0
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_importstmt.py +37 -26
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/_interactive.py +22 -3
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/_livepatch.py +4 -4
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_modules.py +16 -13
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_parse.py +41 -14
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_py.py +36 -30
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/_util.py +23 -46
- {pyflyby-1.8.9/bin → pyflyby-1.9.1/lib/python}/pyflyby/_version.py +1 -1
- {pyflyby-1.8.9 → pyflyby-1.9.1/lib/python/pyflyby.egg-info}/PKG-INFO +1 -1
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby.egg-info/SOURCES.txt +1 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/setup.py +1 -1
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_autoimp.py +44 -7
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_cmdline.py +1 -28
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_importstmt.py +67 -2
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_interactive.py +39 -271
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_modules.py +31 -17
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_parse.py +0 -18
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_py.py +2 -5
- pyflyby-1.9.1/tests/tests_sorts.py +94 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/.pyflyby +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/LICENSE.txt +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/MANIFEST.in +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/README.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/autoipython +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/autopython +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/collect-exports +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/collect-imports +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/create-imports +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/find-import +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/list-bad-xrefs +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/prune-broken-imports +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/__init__.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/__main__.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/_cmdline.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/_log.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/autoimport.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby/importdb.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/pyflyby-diff +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/reformat-imports +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/replace-star-imports +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/bin/transform-imports +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/LICENSE.txt +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/Makefile +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/TODO.txt +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/__init__.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/api.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/autoimp.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/cmdline.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/comms.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/dbg.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/file.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/flags.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/format.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/idents.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/importclns.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/importdb.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/imports2s.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/importstmt.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/interactive.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/livepatch.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/log.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/modules.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/parse.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/py.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/api/util.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/autoipython.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/cli.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/collect_exports.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/collect_imports.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/find_import.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/prune_broken_imports.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/py.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/pyflyby_diff.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/reformat_imports.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/replace_star_imports.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/tidy_imports.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/cli/transform_imports.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/conf.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/index.rst +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/make.bat +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/doc/testing.txt +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/etc/pyflyby/canonical.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/etc/pyflyby/common.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/etc/pyflyby/forget.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/etc/pyflyby/mandatory.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/etc/pyflyby/numpy.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/emacs/pyflyby.el +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/__init__.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/__main__.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/_cmdline.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/_log.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/autoimport.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby/importdb.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby.egg-info/dependency_links.txt +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby.egg-info/entry_points.txt +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby.egg-info/requires.txt +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/lib/python/pyflyby.egg-info/top_level.txt +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/libexec/pyflyby/colordiff +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/libexec/pyflyby/diff-colorize +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/setup.cfg +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/__init__.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_0testconfig.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_docxref.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_file.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_flags.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_format.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_idents.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_importclns.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_importdb.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_imports2s.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_jupyterlab_pyflyby.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_livepatch.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/test_util.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tests/xrefs.py +0 -0
- {pyflyby-1.8.9 → pyflyby-1.9.1}/tox.ini +0 -0
|
@@ -5,11 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
import ast
|
|
8
|
+
import builtins
|
|
8
9
|
import contextlib
|
|
9
10
|
import copy
|
|
10
|
-
import
|
|
11
|
-
from six import exec_, reraise
|
|
12
|
-
from six.moves import builtins
|
|
11
|
+
from six import reraise
|
|
13
12
|
import sys
|
|
14
13
|
import types
|
|
15
14
|
|
|
@@ -23,8 +22,22 @@ from pyflyby._importdb import ImportDB
|
|
|
23
22
|
from pyflyby._importstmt import Import
|
|
24
23
|
from pyflyby._log import logger
|
|
25
24
|
from pyflyby._modules import ModuleHandle
|
|
26
|
-
from pyflyby._parse import PythonBlock, infer_compile_mode
|
|
25
|
+
from pyflyby._parse import PythonBlock, infer_compile_mode, _is_ast_str
|
|
27
26
|
|
|
27
|
+
if sys.version_info >= (3, 12):
|
|
28
|
+
ATTRIBUTE_NAME = "value"
|
|
29
|
+
else:
|
|
30
|
+
ATTRIBUTE_NAME = "s"
|
|
31
|
+
|
|
32
|
+
if sys.version_info > (3, 11):
|
|
33
|
+
LOAD_SHIFT = 1
|
|
34
|
+
else:
|
|
35
|
+
LOAD_SHIFT = 0
|
|
36
|
+
|
|
37
|
+
if sys.version_info > (3, 11):
|
|
38
|
+
LOAD_SHIFT = 1
|
|
39
|
+
else:
|
|
40
|
+
LOAD_SHIFT = 0
|
|
28
41
|
|
|
29
42
|
NoneType = type(None)
|
|
30
43
|
EllipsisType = type(Ellipsis)
|
|
@@ -441,7 +454,8 @@ class _MissingImportFinder(object):
|
|
|
441
454
|
literal_brace_identifiers = set(
|
|
442
455
|
iden
|
|
443
456
|
for f in codeblock.string_literals()
|
|
444
|
-
for iden in brace_identifiers(f
|
|
457
|
+
for iden in brace_identifiers(getattr(f, ATTRIBUTE_NAME))
|
|
458
|
+
)
|
|
445
459
|
if literal_brace_identifiers:
|
|
446
460
|
for ident in literal_brace_identifiers:
|
|
447
461
|
try:
|
|
@@ -450,6 +464,7 @@ class _MissingImportFinder(object):
|
|
|
450
464
|
continue
|
|
451
465
|
symbol_needs_import(ident, self.scopestack)
|
|
452
466
|
self._scan_unused_imports()
|
|
467
|
+
logger.debug("missing: %s, unused: %s", missing_imports, self.unused_imports)
|
|
453
468
|
return missing_imports, self.unused_imports
|
|
454
469
|
|
|
455
470
|
def visit(self, node):
|
|
@@ -498,11 +513,11 @@ class _MissingImportFinder(object):
|
|
|
498
513
|
self.visit(value)
|
|
499
514
|
else:
|
|
500
515
|
raise TypeError(
|
|
501
|
-
"unexpected %s" %
|
|
502
|
-
|
|
503
|
-
elif isinstance(
|
|
504
|
-
|
|
505
|
-
|
|
516
|
+
"unexpected %s" % (", ".join(type(v).__name__ for v in value))
|
|
517
|
+
)
|
|
518
|
+
elif isinstance(
|
|
519
|
+
value, (int, float, complex, str, NoneType, bytes, EllipsisType)
|
|
520
|
+
):
|
|
506
521
|
pass
|
|
507
522
|
else:
|
|
508
523
|
raise TypeError(
|
|
@@ -570,7 +585,7 @@ class _MissingImportFinder(object):
|
|
|
570
585
|
if not isinstance(node.value, ast.List):
|
|
571
586
|
logger.warning("Don't know how to handle __all__ as (%s)" % node.value)
|
|
572
587
|
return
|
|
573
|
-
if not all(
|
|
588
|
+
if not all(_is_ast_str(e) for e in node.value.elts):
|
|
574
589
|
logger.warning("Don't know how to handle __all__ with list elements other than str")
|
|
575
590
|
return
|
|
576
591
|
for e in node.value.elts:
|
|
@@ -578,7 +593,11 @@ class _MissingImportFinder(object):
|
|
|
578
593
|
|
|
579
594
|
def visit_ClassDef(self, node):
|
|
580
595
|
logger.debug("visit_ClassDef(%r)", node)
|
|
581
|
-
|
|
596
|
+
if sys.version_info > (3,12):
|
|
597
|
+
# we don't visit type_params, so autoimport won't work yet for type annotations
|
|
598
|
+
assert node._fields == ('name', 'bases', 'keywords', 'body', 'decorator_list', 'type_params'), node._fields
|
|
599
|
+
else:
|
|
600
|
+
assert node._fields == ('name', 'bases', 'keywords', 'body', 'decorator_list'), node._fields
|
|
582
601
|
self.visit(node.bases)
|
|
583
602
|
self.visit(node.decorator_list)
|
|
584
603
|
# The class's name is only visible to others (not to the body to the
|
|
@@ -609,10 +628,14 @@ class _MissingImportFinder(object):
|
|
|
609
628
|
# scope.
|
|
610
629
|
# - Store the name in the current scope (but not visibly to
|
|
611
630
|
# args/decorator_list).
|
|
612
|
-
|
|
631
|
+
if sys.version_info > (3, 12):
|
|
632
|
+
# we don't visit type_params, so autoimport won't work yet for type annotations
|
|
633
|
+
assert node._fields == ('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment', 'type_params'), node._fields
|
|
634
|
+
else:
|
|
635
|
+
assert node._fields == ('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment'), node._fields
|
|
613
636
|
with self._NewScopeCtx(include_class_scopes=True):
|
|
614
|
-
self.visit(node.args)
|
|
615
637
|
self.visit(node.decorator_list)
|
|
638
|
+
self.visit(node.args)
|
|
616
639
|
if node.returns:
|
|
617
640
|
self.visit(node.returns)
|
|
618
641
|
self._visit_typecomment(node.type_comment)
|
|
@@ -872,6 +895,7 @@ class _MissingImportFinder(object):
|
|
|
872
895
|
# record it as unused.
|
|
873
896
|
oldvalue = scope.get(fullname)
|
|
874
897
|
if isinstance(oldvalue, _UseChecker) and not oldvalue.used:
|
|
898
|
+
logger.debug("Adding to unused %s", oldvalue)
|
|
875
899
|
self.unused_imports.append((oldvalue.lineno, oldvalue.source))
|
|
876
900
|
scope[fullname] = value
|
|
877
901
|
|
|
@@ -1002,11 +1026,12 @@ class _MissingImportFinder(object):
|
|
|
1002
1026
|
if unused_imports is None:
|
|
1003
1027
|
return
|
|
1004
1028
|
scope = self.scopestack[-1]
|
|
1005
|
-
for name, value in
|
|
1029
|
+
for name, value in scope.items():
|
|
1006
1030
|
if not isinstance(value, _UseChecker):
|
|
1007
1031
|
continue
|
|
1008
1032
|
if value.used:
|
|
1009
1033
|
continue
|
|
1034
|
+
logger.debug("Also Adding to usunsed import: %s ", value)
|
|
1010
1035
|
unused_imports.append(( value.lineno, value.source ))
|
|
1011
1036
|
unused_imports.sort()
|
|
1012
1037
|
|
|
@@ -1128,13 +1153,19 @@ def _find_loads_without_stores_in_code(co, loads_without_stores):
|
|
|
1128
1153
|
% (type(co).__name__,))
|
|
1129
1154
|
# Initialize local constants for fast access.
|
|
1130
1155
|
from opcode import HAVE_ARGUMENT, EXTENDED_ARG, opmap
|
|
1156
|
+
|
|
1131
1157
|
LOAD_ATTR = opmap['LOAD_ATTR']
|
|
1132
|
-
LOAD_METHOD
|
|
1158
|
+
LOAD_METHOD = opmap['LOAD_METHOD']
|
|
1133
1159
|
LOAD_GLOBAL = opmap['LOAD_GLOBAL']
|
|
1134
1160
|
LOAD_NAME = opmap['LOAD_NAME']
|
|
1135
1161
|
STORE_ATTR = opmap['STORE_ATTR']
|
|
1136
1162
|
STORE_GLOBAL = opmap['STORE_GLOBAL']
|
|
1137
1163
|
STORE_NAME = opmap['STORE_NAME']
|
|
1164
|
+
|
|
1165
|
+
if sys.version_info > (3, 11):
|
|
1166
|
+
CACHE = opmap["CACHE"]
|
|
1167
|
+
else:
|
|
1168
|
+
CACHE = object()
|
|
1138
1169
|
# Keep track of the partial name so far that started with a LOAD_GLOBAL.
|
|
1139
1170
|
# If ``pending`` is not None, then it is a list representing the name
|
|
1140
1171
|
# components we've seen so far.
|
|
@@ -1227,6 +1258,8 @@ def _find_loads_without_stores_in_code(co, loads_without_stores):
|
|
|
1227
1258
|
c = bytecode[i]
|
|
1228
1259
|
op = _op(c)
|
|
1229
1260
|
i += 1
|
|
1261
|
+
if op == CACHE:
|
|
1262
|
+
continue
|
|
1230
1263
|
if op >= HAVE_ARGUMENT:
|
|
1231
1264
|
oparg = bytecode[i] | extended_arg
|
|
1232
1265
|
extended_arg = 0
|
|
@@ -1258,7 +1291,13 @@ def _find_loads_without_stores_in_code(co, loads_without_stores):
|
|
|
1258
1291
|
loads_before_label_without_stores.add(fullname)
|
|
1259
1292
|
# Fall through.
|
|
1260
1293
|
|
|
1261
|
-
if op
|
|
1294
|
+
if op is LOAD_GLOBAL:
|
|
1295
|
+
# Starting with 3.11, the low bit is used to tell whether to
|
|
1296
|
+
# push an extra null on the stack, so we need to >> 1
|
|
1297
|
+
# >> 0 does nothing
|
|
1298
|
+
pending = [co.co_names[oparg >> LOAD_SHIFT]]
|
|
1299
|
+
continue
|
|
1300
|
+
if op is LOAD_NAME:
|
|
1262
1301
|
pending = [co.co_names[oparg]]
|
|
1263
1302
|
continue
|
|
1264
1303
|
|
|
@@ -1489,7 +1528,7 @@ def find_missing_imports(arg, namespaces):
|
|
|
1489
1528
|
``list`` of ``DottedIdentifier``
|
|
1490
1529
|
"""
|
|
1491
1530
|
namespaces = ScopeStack(namespaces)
|
|
1492
|
-
if isinstance(arg, (DottedIdentifier,
|
|
1531
|
+
if isinstance(arg, (DottedIdentifier, str)):
|
|
1493
1532
|
try:
|
|
1494
1533
|
arg = DottedIdentifier(arg)
|
|
1495
1534
|
except BadDottedIdentifierError:
|
|
@@ -1626,7 +1665,7 @@ def _try_import(imp, namespace):
|
|
|
1626
1665
|
# then (3) copy into the user's namespace if it didn't already exist.
|
|
1627
1666
|
scratch_namespace = {}
|
|
1628
1667
|
try:
|
|
1629
|
-
|
|
1668
|
+
exec(stmt, scratch_namespace)
|
|
1630
1669
|
imported = scratch_namespace[name0]
|
|
1631
1670
|
except Exception as e:
|
|
1632
1671
|
logger.warning("Error attempting to %r: %s: %s", stmt, type(e).__name__, e,
|
|
@@ -1897,7 +1936,7 @@ def auto_eval(arg, filename=None, mode=None,
|
|
|
1897
1936
|
"""
|
|
1898
1937
|
if isinstance(flags, int):
|
|
1899
1938
|
assert isinstance(flags, CompilerFlags)
|
|
1900
|
-
if isinstance(arg, (
|
|
1939
|
+
if isinstance(arg, (str, Filename, FileText, PythonBlock)):
|
|
1901
1940
|
block = PythonBlock(arg, filename=filename, flags=flags,
|
|
1902
1941
|
auto_flags=auto_flags)
|
|
1903
1942
|
flags = block.flags
|
|
@@ -4,7 +4,8 @@ from __future__ import print_function
|
|
|
4
4
|
from pyflyby._imports2s import (SourceToSourceFileImportsTransformation,
|
|
5
5
|
SourceToSourceImportBlockTransformation,
|
|
6
6
|
fix_unused_and_missing_imports,
|
|
7
|
-
replace_star_imports
|
|
7
|
+
replace_star_imports,
|
|
8
|
+
reformat_import_statements)
|
|
8
9
|
from pyflyby._importstmt import Import
|
|
9
10
|
from pyflyby._log import logger
|
|
10
11
|
import six
|
|
@@ -92,8 +93,6 @@ def comm_close_handler(comm, message):
|
|
|
92
93
|
|
|
93
94
|
|
|
94
95
|
def _reformat_helper(input_code, imports):
|
|
95
|
-
from pyflyby._imports2s import reformat_import_statements
|
|
96
|
-
|
|
97
96
|
if PYFLYBY_START_MSG in input_code:
|
|
98
97
|
before, bmarker, middle = input_code.partition(PYFLYBY_START_MSG)
|
|
99
98
|
else:
|
|
@@ -131,8 +130,8 @@ def extract_import_statements(text):
|
|
|
131
130
|
extracting the import statements.
|
|
132
131
|
"""
|
|
133
132
|
transformer = SourceToSourceFileImportsTransformation(text)
|
|
134
|
-
imports = '\n'.join([str(im.pretty_print()) for im in transformer.import_blocks])
|
|
135
|
-
remaining_code = "\n".join([str(st.pretty_print()) if not isinstance(st, SourceToSourceImportBlockTransformation) else "" for st in transformer.blocks])
|
|
133
|
+
imports = '\n'.join([str(im.pretty_print()).strip() for im in transformer.import_blocks])
|
|
134
|
+
remaining_code = "\n".join([str(st.pretty_print()).strip() if not isinstance(st, SourceToSourceImportBlockTransformation) else "" for st in transformer.blocks])
|
|
136
135
|
return imports, remaining_code
|
|
137
136
|
|
|
138
137
|
def collect_code_with_imports_on_top(imports: str, cell_array):
|
|
@@ -141,16 +140,18 @@ def collect_code_with_imports_on_top(imports: str, cell_array):
|
|
|
141
140
|
+ "\n"
|
|
142
141
|
+ "\n".join(
|
|
143
142
|
[
|
|
144
|
-
cell["text"] if cell["type"] == "code" else ""
|
|
143
|
+
cell["text"] if cell["type"] == "code" and not cell.get("ignore", False) else ""
|
|
145
144
|
for cell in cell_array
|
|
146
145
|
]
|
|
147
146
|
)
|
|
148
147
|
)
|
|
149
148
|
|
|
150
149
|
def run_tidy_imports(code):
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
return str(
|
|
151
|
+
reformat_import_statements(
|
|
152
|
+
fix_unused_and_missing_imports(
|
|
153
|
+
replace_star_imports(code)
|
|
154
|
+
)
|
|
154
155
|
)
|
|
155
156
|
)
|
|
156
157
|
|
|
@@ -192,12 +193,20 @@ def comm_open_handler(comm, message):
|
|
|
192
193
|
# while clubbing similar imports and re-ordering them.
|
|
193
194
|
import_statements, processed_cell_array = "", []
|
|
194
195
|
for cell in cell_array:
|
|
196
|
+
ignore = False
|
|
195
197
|
text = cell.get("text")
|
|
196
198
|
cell_type = cell.get("type")
|
|
197
199
|
if cell_type == "code":
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
try:
|
|
201
|
+
imports, text = extract_import_statements(text)
|
|
202
|
+
import_statements += (imports + "\n")
|
|
203
|
+
except SyntaxError:
|
|
204
|
+
# If a cell triggers Syntax Error, we set ignore to
|
|
205
|
+
# True and don't include it when running tidy-imports
|
|
206
|
+
# For eg. this is triggered due to cells with magic
|
|
207
|
+
# commands
|
|
208
|
+
ignore = True
|
|
209
|
+
processed_cell_array.append({"text": text, "type": cell_type, "ignore": ignore})
|
|
201
210
|
code_with_collected_imports = collect_code_with_imports_on_top(import_statements, processed_cell_array)
|
|
202
211
|
code_post_tidy_imports = run_tidy_imports(code_with_collected_imports)
|
|
203
212
|
import_statements, _ = extract_import_statements(code_post_tidy_imports)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# License: MIT http://opensource.org/licenses/MIT
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import builtins
|
|
7
7
|
from contextlib import contextmanager
|
|
8
8
|
import errno
|
|
9
9
|
from functools import wraps
|
|
@@ -14,9 +14,6 @@ import sys
|
|
|
14
14
|
import time
|
|
15
15
|
from types import CodeType, FrameType, TracebackType
|
|
16
16
|
|
|
17
|
-
import six
|
|
18
|
-
from six.moves import builtins
|
|
19
|
-
|
|
20
17
|
from collections.abc import Callable
|
|
21
18
|
|
|
22
19
|
from pyflyby._file import Filename
|
|
@@ -349,7 +346,8 @@ def _debug_code(arg, globals=None, locals=None, auto_import=True, tty="/dev/tty"
|
|
|
349
346
|
print("Entering debugger. Use 'n' to step, 'c' to run, 'q' to stop.")
|
|
350
347
|
print("")
|
|
351
348
|
from ._parse import PythonStatement, PythonBlock, FileText
|
|
352
|
-
|
|
349
|
+
|
|
350
|
+
if isinstance(arg, (str, PythonStatement, PythonBlock, FileText)):
|
|
353
351
|
# Compile the block so that we can get the right compile mode.
|
|
354
352
|
arg = PythonBlock(arg)
|
|
355
353
|
# TODO: enter text into linecache
|
|
@@ -502,8 +500,9 @@ def debugger(*args, **kwargs):
|
|
|
502
500
|
# TODO: capture globals/locals when relevant.
|
|
503
501
|
wait_for_debugger_to_attach(arg)
|
|
504
502
|
return
|
|
505
|
-
if isinstance(
|
|
506
|
-
|
|
503
|
+
if isinstance(
|
|
504
|
+
arg, (str, PythonStatement, PythonBlock, FileText, CodeType, Callable)
|
|
505
|
+
):
|
|
507
506
|
_debug_code(arg, globals=globals, locals=locals, tty=tty)
|
|
508
507
|
on_continue()
|
|
509
508
|
return
|
|
@@ -1013,12 +1012,12 @@ def inject(pid, statements, wait=True, show_gdb_output=False):
|
|
|
1013
1012
|
"""
|
|
1014
1013
|
import subprocess
|
|
1015
1014
|
os.kill(pid, 0) # raises OSError "No such process" unless pid exists
|
|
1016
|
-
if isinstance(statements,
|
|
1015
|
+
if isinstance(statements, str):
|
|
1017
1016
|
statements = (statements,)
|
|
1018
1017
|
else:
|
|
1019
1018
|
statements = tuple(statements)
|
|
1020
1019
|
for statement in statements:
|
|
1021
|
-
if not isinstance(statement,
|
|
1020
|
+
if not isinstance(statement, str):
|
|
1022
1021
|
raise TypeError(
|
|
1023
1022
|
"Expected iterable of strings, not %r" % (type(statement),))
|
|
1024
1023
|
# Based on
|
|
@@ -26,8 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
import re
|
|
29
|
-
import
|
|
30
|
-
from six.moves import builtins
|
|
29
|
+
import builtins
|
|
31
30
|
from textwrap import dedent
|
|
32
31
|
|
|
33
32
|
from epydoc.apidoc import (ClassDoc, ModuleDoc, PropertyDoc,
|
|
@@ -348,7 +347,7 @@ class XrefScanner(object):
|
|
|
348
347
|
return ''
|
|
349
348
|
|
|
350
349
|
def scan_tree(tree):
|
|
351
|
-
if isinstance(tree,
|
|
350
|
+
if isinstance(tree, str):
|
|
352
351
|
return tree
|
|
353
352
|
variables = [scan_tree(child) for child in tree.children]
|
|
354
353
|
if tree.tag == 'link':
|
|
@@ -8,11 +8,8 @@ from functools import total_ordering
|
|
|
8
8
|
import io
|
|
9
9
|
import os
|
|
10
10
|
import re
|
|
11
|
-
import six
|
|
12
11
|
import sys
|
|
13
12
|
|
|
14
|
-
from six import string_types
|
|
15
|
-
|
|
16
13
|
from pyflyby._util import cached_attribute, cmp, memoize
|
|
17
14
|
|
|
18
15
|
|
|
@@ -34,13 +31,13 @@ class Filename(object):
|
|
|
34
31
|
def __new__(cls, arg):
|
|
35
32
|
if isinstance(arg, cls):
|
|
36
33
|
return arg
|
|
37
|
-
if isinstance(arg,
|
|
34
|
+
if isinstance(arg, str):
|
|
38
35
|
return cls._from_filename(arg)
|
|
39
36
|
raise TypeError
|
|
40
37
|
|
|
41
38
|
@classmethod
|
|
42
39
|
def _from_filename(cls, filename):
|
|
43
|
-
if not isinstance(filename,
|
|
40
|
+
if not isinstance(filename, str):
|
|
44
41
|
raise TypeError
|
|
45
42
|
filename = str(filename)
|
|
46
43
|
if not filename:
|
|
@@ -336,7 +333,7 @@ FilePos._ONE_ONE = FilePos._from_lc(1, 1)
|
|
|
336
333
|
|
|
337
334
|
|
|
338
335
|
@total_ordering
|
|
339
|
-
class FileText
|
|
336
|
+
class FileText:
|
|
340
337
|
"""
|
|
341
338
|
Represents a contiguous sequence of lines from a file.
|
|
342
339
|
"""
|
|
@@ -372,7 +369,7 @@ class FileText(object):
|
|
|
372
369
|
return cls(read_file(arg), filename=filename, startpos=startpos)
|
|
373
370
|
elif hasattr(arg, "__text__"):
|
|
374
371
|
return FileText(arg.__text__(), filename=filename, startpos=startpos)
|
|
375
|
-
elif isinstance(arg,
|
|
372
|
+
elif isinstance(arg, str):
|
|
376
373
|
self = object.__new__(cls)
|
|
377
374
|
self.joined = arg
|
|
378
375
|
else:
|
|
@@ -389,7 +386,7 @@ class FileText(object):
|
|
|
389
386
|
def _from_lines(cls, lines, filename, startpos):
|
|
390
387
|
assert type(lines) is tuple
|
|
391
388
|
assert len(lines) > 0
|
|
392
|
-
assert isinstance(lines[0],
|
|
389
|
+
assert isinstance(lines[0], str)
|
|
393
390
|
assert not lines[-1].endswith("\n")
|
|
394
391
|
self = object.__new__(cls)
|
|
395
392
|
self.lines = lines
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
import __future__
|
|
8
8
|
import ast
|
|
9
9
|
import operator
|
|
10
|
-
import six
|
|
11
10
|
from six.moves import reduce
|
|
12
11
|
import warnings
|
|
13
12
|
|
|
14
13
|
from pyflyby._util import cached_attribute
|
|
14
|
+
from typing import Tuple
|
|
15
15
|
|
|
16
16
|
# Initialize mappings from compiler_flag to feature name and vice versa.
|
|
17
17
|
_FLAG2NAME = {}
|
|
@@ -49,6 +49,10 @@ class CompilerFlags(int):
|
|
|
49
49
|
|
|
50
50
|
"""
|
|
51
51
|
|
|
52
|
+
# technically both those are compiler flags, but we can't use Self. May need typing_extensions ?
|
|
53
|
+
_ZERO:int
|
|
54
|
+
_UNKNOWN: int
|
|
55
|
+
|
|
52
56
|
def __new__(cls, *args):
|
|
53
57
|
"""
|
|
54
58
|
Construct a new ``CompilerFlags`` instance.
|
|
@@ -72,7 +76,7 @@ class CompilerFlags(int):
|
|
|
72
76
|
' flags values change between Python versions. If you are sure use .from_int',
|
|
73
77
|
DeprecationWarning, stacklevel=2)
|
|
74
78
|
return cls.from_int(arg)
|
|
75
|
-
elif isinstance(arg,
|
|
79
|
+
elif isinstance(arg, str):
|
|
76
80
|
return cls.from_str(arg)
|
|
77
81
|
elif isinstance(arg, ast.AST):
|
|
78
82
|
return cls.from_ast(arg)
|
|
@@ -100,7 +104,7 @@ class CompilerFlags(int):
|
|
|
100
104
|
raise ValueError
|
|
101
105
|
|
|
102
106
|
#assert flags == [0x10000, 0x8000], flags
|
|
103
|
-
|
|
107
|
+
|
|
104
108
|
return cls.from_int(reduce(operator.or_, flags))
|
|
105
109
|
|
|
106
110
|
@classmethod
|
|
@@ -117,7 +121,7 @@ class CompilerFlags(int):
|
|
|
117
121
|
return self
|
|
118
122
|
|
|
119
123
|
@classmethod
|
|
120
|
-
def from_str(cls, arg):
|
|
124
|
+
def from_str(cls, arg:str):
|
|
121
125
|
try:
|
|
122
126
|
flag = _NAME2FLAG[arg]
|
|
123
127
|
except KeyError:
|
|
@@ -153,7 +157,7 @@ class CompilerFlags(int):
|
|
|
153
157
|
return cls(flags)
|
|
154
158
|
|
|
155
159
|
@cached_attribute
|
|
156
|
-
def names(self):
|
|
160
|
+
def names(self) -> Tuple[str]:
|
|
157
161
|
return tuple(
|
|
158
162
|
n
|
|
159
163
|
for f, n in _FLAGNAME_ITEMS
|
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
import six
|
|
8
|
-
|
|
9
|
-
|
|
10
7
|
class FormatParams(object):
|
|
11
8
|
max_line_length = None
|
|
12
9
|
_max_line_lenght_default = 79
|
|
@@ -24,14 +21,16 @@ class FormatParams(object):
|
|
|
24
21
|
for arg in args:
|
|
25
22
|
if arg is None:
|
|
26
23
|
pass
|
|
27
|
-
elif isinstance(arg, cls):
|
|
24
|
+
elif isinstance(arg, cls) or hasattr(self, "__dict__"):
|
|
28
25
|
dicts.append(arg.__dict__)
|
|
29
26
|
else:
|
|
30
|
-
raise TypeError
|
|
27
|
+
raise TypeError(
|
|
28
|
+
"expected None, or instance of %s cls, got %s" % (cls, arg)
|
|
29
|
+
)
|
|
31
30
|
if kwargs:
|
|
32
31
|
dicts.append(kwargs)
|
|
33
32
|
for kwargs in dicts:
|
|
34
|
-
for key, value in
|
|
33
|
+
for key, value in kwargs.items():
|
|
35
34
|
if hasattr(self, key):
|
|
36
35
|
setattr(self, key, value)
|
|
37
36
|
else:
|
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
from functools import total_ordering
|
|
8
8
|
from keyword import kwlist
|
|
9
9
|
import re
|
|
10
|
-
import six
|
|
11
10
|
|
|
12
11
|
from pyflyby._util import cached_attribute, cmp
|
|
13
12
|
|
|
13
|
+
from typing import Optional, Tuple, Dict
|
|
14
|
+
|
|
14
15
|
|
|
15
16
|
# Don't consider "print" a keyword, in order to be compatible with user code
|
|
16
17
|
# that uses "from __future__ import print_function".
|
|
@@ -46,12 +47,7 @@ def dotted_prefixes(dotted_name, reverse=False):
|
|
|
46
47
|
return result
|
|
47
48
|
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
_dotted_name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*([.][a-zA-Z_][a-zA-Z0-9_]*)*$")
|
|
51
|
-
_dotted_name_prefix_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*([.][a-zA-Z_][a-zA-Z0-9_]*)*[.]?$")
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def is_identifier(s, dotted=False, prefix=False):
|
|
50
|
+
def is_identifier(s: str, dotted: bool = False, prefix: bool = False):
|
|
55
51
|
"""
|
|
56
52
|
Return whether ``s`` is a valid Python identifier name.
|
|
57
53
|
|
|
@@ -111,7 +107,7 @@ def is_identifier(s, dotted=False, prefix=False):
|
|
|
111
107
|
:rtype:
|
|
112
108
|
``bool``
|
|
113
109
|
"""
|
|
114
|
-
if not isinstance(s,
|
|
110
|
+
if not isinstance(s, str):
|
|
115
111
|
raise TypeError("is_identifier(): expected a string; got a %s"
|
|
116
112
|
% (type(s).__name__,))
|
|
117
113
|
if prefix:
|
|
@@ -140,11 +136,15 @@ class BadDottedIdentifierError(ValueError):
|
|
|
140
136
|
|
|
141
137
|
# TODO: Use in various places, esp where e.g. dotted_prefixes is used.
|
|
142
138
|
@total_ordering
|
|
143
|
-
class DottedIdentifier
|
|
139
|
+
class DottedIdentifier:
|
|
140
|
+
name: str
|
|
141
|
+
parts: Tuple[str, ...]
|
|
142
|
+
scope_info: Optional[Dict]
|
|
143
|
+
|
|
144
144
|
def __new__(cls, arg, scope_info=None):
|
|
145
145
|
if isinstance(arg, cls):
|
|
146
146
|
return arg
|
|
147
|
-
if isinstance(arg,
|
|
147
|
+
if isinstance(arg, str):
|
|
148
148
|
return cls._from_name(arg, scope_info)
|
|
149
149
|
if isinstance(arg, (tuple, list)):
|
|
150
150
|
return cls._from_name(".".join(arg), scope_info)
|
|
@@ -17,6 +17,8 @@ from pyflyby._parse import PythonBlock
|
|
|
17
17
|
from pyflyby._util import (cached_attribute, cmp, partition,
|
|
18
18
|
stable_unique)
|
|
19
19
|
|
|
20
|
+
from typing import Dict
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
class NoSuchImportError(ValueError):
|
|
22
24
|
pass
|
|
@@ -213,8 +215,8 @@ class ImportSet(object):
|
|
|
213
215
|
"""
|
|
214
216
|
:return:
|
|
215
217
|
(mapping from name to __future__ imports,
|
|
216
|
-
|
|
217
|
-
|
|
218
|
+
mapping from name to non-'from' imports,
|
|
219
|
+
mapping from name to 'from' imports)
|
|
218
220
|
"""
|
|
219
221
|
ftr_imports = defaultdict(set)
|
|
220
222
|
pkg_imports = defaultdict(set)
|
|
@@ -228,9 +230,9 @@ class ImportSet(object):
|
|
|
228
230
|
else:
|
|
229
231
|
frm_imports[module_name].add(imp)
|
|
230
232
|
return tuple(
|
|
231
|
-
dict(
|
|
232
|
-
|
|
233
|
-
|
|
233
|
+
dict((k, frozenset(v)) for k, v in imports.items())
|
|
234
|
+
for imports in [ftr_imports, pkg_imports, frm_imports]
|
|
235
|
+
)
|
|
234
236
|
|
|
235
237
|
def get_statements(self, separate_from_imports=True):
|
|
236
238
|
"""
|
|
@@ -261,8 +263,8 @@ class ImportSet(object):
|
|
|
261
263
|
if not separate_from_imports:
|
|
262
264
|
def union_dicts(*dicts):
|
|
263
265
|
result = {}
|
|
264
|
-
for label,
|
|
265
|
-
for k, v in
|
|
266
|
+
for label, dct in enumerate(dicts):
|
|
267
|
+
for k, v in dct.items():
|
|
266
268
|
result[(k, label)] = v
|
|
267
269
|
return result
|
|
268
270
|
groups = [groups[0], union_dicts(*groups[1:])]
|
|
@@ -317,8 +319,7 @@ class ImportSet(object):
|
|
|
317
319
|
d = defaultdict(list)
|
|
318
320
|
for imp in self._importset:
|
|
319
321
|
d[imp.import_as].append(imp)
|
|
320
|
-
return dict(
|
|
321
|
-
for k, v in six.iteritems(d) )
|
|
322
|
+
return dict((k, tuple(sorted(stable_unique(v)))) for k, v in d.items())
|
|
322
323
|
|
|
323
324
|
@cached_attribute
|
|
324
325
|
def member_names(self):
|
|
@@ -347,8 +348,7 @@ class ImportSet(object):
|
|
|
347
348
|
for prefix in prefixes[1:]:
|
|
348
349
|
splt = prefix.rsplit(".", 1)
|
|
349
350
|
d[splt[0]].add(splt[1])
|
|
350
|
-
return dict(
|
|
351
|
-
for k, v in six.iteritems(d) )
|
|
351
|
+
return dict((k, tuple(sorted(v))) for k, v in d.items())
|
|
352
352
|
|
|
353
353
|
@cached_attribute
|
|
354
354
|
def conflicting_imports(self):
|
|
@@ -364,10 +364,7 @@ class ImportSet(object):
|
|
|
364
364
|
:rtype:
|
|
365
365
|
``bool``
|
|
366
366
|
"""
|
|
367
|
-
return tuple(
|
|
368
|
-
k
|
|
369
|
-
for k, v in six.iteritems(self.by_import_as)
|
|
370
|
-
if len(v) > 1 and k != "*")
|
|
367
|
+
return tuple(k for k, v in self.by_import_as.items() if len(v) > 1 and k != "*")
|
|
371
368
|
|
|
372
369
|
@cached_attribute
|
|
373
370
|
def flags(self):
|
|
@@ -522,6 +519,8 @@ class ImportMap(object):
|
|
|
522
519
|
An ``ImportMap`` is an immutable data structure.
|
|
523
520
|
"""
|
|
524
521
|
|
|
522
|
+
_data: Dict
|
|
523
|
+
|
|
525
524
|
def __new__(cls, arg):
|
|
526
525
|
if isinstance(arg, cls):
|
|
527
526
|
return arg
|
|
@@ -565,7 +564,7 @@ class ImportMap(object):
|
|
|
565
564
|
return self._data.items()
|
|
566
565
|
|
|
567
566
|
def iteritems(self):
|
|
568
|
-
return
|
|
567
|
+
return self._data.items()
|
|
569
568
|
|
|
570
569
|
def iterkeys(self):
|
|
571
570
|
return six.iterkeys(self._data)
|