in usort/sorting.py [0:0]
def is_sortable_import(self, stmt: cst.CSTNode) -> bool:
"""
Determine if any individual statement is sortable or should be a barrier.
Handles skip directives, configured side effect modules, and star imports.
"""
if isinstance(stmt, cst.SimpleStatementLine):
# from foo import (
# bar,
# ) # usort:skip
comment = stmt.trailing_whitespace.comment
if self.has_skip_comment(comment):
return False
# N.b. `body` is a list, because the SimpleStatementLine might have
# semicolons. We only look at the first, which is probably the most
# dangerous thing in here.
#
# If black is run, it will put the semicolon pieces on different lines,
# but we don't want to do that until we reflow and handle directives
# like noqa. TODO do that before calling is_sortable_import, and assert
# that it's not a compound statement line.
if isinstance(stmt.body[0], cst.ImportFrom):
# from foo import ( # usort:skip
# bar,
# )
if isinstance(stmt.body[0].lpar, cst.LeftParen) and isinstance(
stmt.body[0].lpar.whitespace_after, cst.ParenthesizedWhitespace
):
comment = stmt.body[0].lpar.whitespace_after.first_line.comment
if self.has_skip_comment(comment):
return False
# `from x import *` is a barrier
if isinstance(stmt.body[0].names, cst.ImportStar):
return False
# check for side effect modules, but ignore local (from .) imports (TODO?)
elif stmt.body[0].module is not None:
base = cst.helpers.get_full_name_for_node_or_raise(
stmt.body[0].module
)
names = [name.evaluated_name for name in stmt.body[0].names]
if self.config.is_side_effect_import(base, names):
return False
return True
elif isinstance(stmt.body[0], cst.Import):
base = ""
names = [name.evaluated_name for name in stmt.body[0].names]
if self.config.is_side_effect_import(base, names):
return False
return True
else:
return False
else:
return False