Skip to content

Commit

Permalink
Replace x[:] with x.copy() (python#14949)
Browse files Browse the repository at this point in the history
This PR fixes the
[`FURB145`](https://github.com/dosisod/refurb/blob/master/docs/checks.md#furb145-no-slice-copy)
error code from Refurb. In my (limited) testing, using `x.copy()` is
faster then both the interpreted and compiled versions of `x[:]` (see
python#14887 (comment)).

See python#14887 for more info.
  • Loading branch information
dosisod authored Apr 24, 2023
1 parent 7be0d4b commit 186432d
Show file tree
Hide file tree
Showing 23 changed files with 39 additions and 39 deletions.
2 changes: 1 addition & 1 deletion mypy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -1911,7 +1911,7 @@ def __init__(
self.caller_state = caller_state
self.caller_line = caller_line
if caller_state:
self.import_context = caller_state.import_context[:]
self.import_context = caller_state.import_context.copy()
self.import_context.append((caller_state.xpath, caller_line))
else:
self.import_context = []
Expand Down
2 changes: 1 addition & 1 deletion mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4472,7 +4472,7 @@ def infer_lambda_type_using_context(
is_ellipsis_args=False,
arg_types=[AnyType(TypeOfAny.special_form)] * len(arg_kinds),
arg_kinds=arg_kinds,
arg_names=e.arg_names[:],
arg_names=e.arg_names.copy(),
)

if ARG_STAR in arg_kinds or ARG_STAR2 in arg_kinds:
Expand Down
2 changes: 1 addition & 1 deletion mypy/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,7 @@ def find_matching_overload_items(
if not res:
# Falling back to all items if we can't find a match is pretty arbitrary, but
# it maintains backward compatibility.
res = items[:]
res = items.copy()
return res


Expand Down
4 changes: 2 additions & 2 deletions mypy/dmypy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ def fine_grained_increment_follow_imports(self, sources: list[BuildSource]) -> l
messages = fine_grained_manager.update(changed, [], followed=True)

# Follow deps from changed modules (still within graph).
worklist = changed[:]
worklist = changed.copy()
while worklist:
module = worklist.pop()
if module[0] not in graph:
Expand Down Expand Up @@ -706,7 +706,7 @@ def find_reachable_changed_modules(
"""
changed = []
new_files = []
worklist = roots[:]
worklist = roots.copy()
seen.update(source.module for source in worklist)
while worklist:
nxt = worklist.pop()
Expand Down
4 changes: 2 additions & 2 deletions mypy/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,11 +338,11 @@ def current_module(self) -> str | None:

def import_context(self) -> list[tuple[str, int]]:
"""Return a copy of the import context."""
return self.import_ctx[:]
return self.import_ctx.copy()

def set_import_context(self, ctx: list[tuple[str, int]]) -> None:
"""Replace the entire import context with a new value."""
self.import_ctx = ctx[:]
self.import_ctx = ctx.copy()

def report(
self,
Expand Down
2 changes: 1 addition & 1 deletion mypy/memprofile.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def visit(o: object) -> None:
objs.append(o)
seen.add(id(o))

for obj in objs[:]:
for obj in objs.copy():
if type(obj) is FakeInfo:
# Processing these would cause a crash.
continue
Expand Down
2 changes: 1 addition & 1 deletion mypy/mro.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def linearize_hierarchy(


def merge(seqs: list[list[TypeInfo]]) -> list[TypeInfo]:
seqs = [s[:] for s in seqs]
seqs = [s.copy() for s in seqs]
result: list[TypeInfo] = []
while True:
seqs = [s for s in seqs if s]
Expand Down
2 changes: 1 addition & 1 deletion mypy/semanal_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def process_top_levels(graph: Graph, scc: list[str], patches: Patches) -> None:
# Initially all namespaces in the SCC are incomplete (well they are empty).
state.manager.incomplete_namespaces.update(scc)

worklist = scc[:]
worklist = scc.copy()
# HACK: process core stuff first. This is mostly needed to support defining
# named tuples in builtin SCC.
if all(m in worklist for m in core_modules):
Expand Down
2 changes: 1 addition & 1 deletion mypy/server/deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -1027,7 +1027,7 @@ def visit_tuple_type(self, typ: TupleType) -> list[str]:
def visit_type_type(self, typ: TypeType) -> list[str]:
triggers = self.get_type_triggers(typ.item)
if not self.use_logical_deps:
old_triggers = triggers[:]
old_triggers = triggers.copy()
for trigger in old_triggers:
triggers.append(trigger.rstrip(">") + ".__init__>")
triggers.append(trigger.rstrip(">") + ".__new__>")
Expand Down
6 changes: 3 additions & 3 deletions mypy/server/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def __init__(self, result: BuildResult) -> None:
# Merge in any root dependencies that may not have been loaded
merge_dependencies(manager.load_fine_grained_deps(FAKE_ROOT_MODULE), self.deps)
self.previous_targets_with_errors = manager.errors.targets()
self.previous_messages: list[str] = result.errors[:]
self.previous_messages: list[str] = result.errors.copy()
# Module, if any, that had blocking errors in the last run as (id, path) tuple.
self.blocking_error: tuple[str, str] | None = None
# Module that we haven't processed yet but that are known to be stale.
Expand Down Expand Up @@ -302,7 +302,7 @@ def update(
break

messages = sort_messages_preserving_file_order(messages, self.previous_messages)
self.previous_messages = messages[:]
self.previous_messages = messages.copy()
return messages

def trigger(self, target: str) -> list[str]:
Expand All @@ -322,7 +322,7 @@ def trigger(self, target: str) -> list[str]:
)
# Preserve state needed for the next update.
self.previous_targets_with_errors = self.manager.errors.targets()
self.previous_messages = self.manager.errors.new_messages()[:]
self.previous_messages = self.manager.errors.new_messages().copy()
return self.update(changed_modules, [])

def flush_cache(self) -> None:
Expand Down
2 changes: 1 addition & 1 deletion mypy/strconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def visit_func_def(self, o: mypy.nodes.FuncDef) -> str:
return self.dump(a, o)

def visit_overloaded_func_def(self, o: mypy.nodes.OverloadedFuncDef) -> str:
a: Any = o.items[:]
a: Any = o.items.copy()
if o.type:
a.insert(0, o.type)
if o.impl:
Expand Down
2 changes: 1 addition & 1 deletion mypy/stubgenc.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ def add_typing_import(output: list[str]) -> list[str]:
if names:
return [f"from typing import {', '.join(names)}", ""] + output
else:
return output[:]
return output.copy()


def get_members(obj: object) -> list[tuple[str, Any]]:
Expand Down
2 changes: 1 addition & 1 deletion mypy/test/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ def local_sys_path_set() -> Iterator[None]:
This can be used by test cases that do runtime imports, for example
by the stubgen tests.
"""
old_sys_path = sys.path[:]
old_sys_path = sys.path.copy()
if not ("" in sys.path or "." in sys.path):
sys.path.insert(0, "")
try:
Expand Down
4 changes: 2 additions & 2 deletions mypy/test/teststubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@
@contextlib.contextmanager
def use_tmp_dir(mod_name: str) -> Iterator[str]:
current = os.getcwd()
current_syspath = sys.path[:]
current_syspath = sys.path.copy()
with tempfile.TemporaryDirectory() as tmp:
try:
os.chdir(tmp)
if sys.path[0] != tmp:
sys.path.insert(0, tmp)
yield tmp
finally:
sys.path = current_syspath[:]
sys.path = current_syspath.copy()
if mod_name in sys.modules:
del sys.modules[mod_name]

Expand Down
14 changes: 7 additions & 7 deletions mypy/treetransform.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,18 @@ def __init__(self) -> None:
def visit_mypy_file(self, node: MypyFile) -> MypyFile:
assert self.test_only, "This visitor should not be used for whole files."
# NOTE: The 'names' and 'imports' instance variables will be empty!
ignored_lines = {line: codes[:] for line, codes in node.ignored_lines.items()}
ignored_lines = {line: codes.copy() for line, codes in node.ignored_lines.items()}
new = MypyFile(self.statements(node.defs), [], node.is_bom, ignored_lines=ignored_lines)
new._fullname = node._fullname
new.path = node.path
new.names = SymbolTable()
return new

def visit_import(self, node: Import) -> Import:
return Import(node.ids[:])
return Import(node.ids.copy())

def visit_import_from(self, node: ImportFrom) -> ImportFrom:
return ImportFrom(node.id, node.relative, node.names[:])
return ImportFrom(node.id, node.relative, node.names.copy())

def visit_import_all(self, node: ImportAll) -> ImportAll:
return ImportAll(node.id, node.relative)
Expand Down Expand Up @@ -267,10 +267,10 @@ def visit_class_def(self, node: ClassDef) -> ClassDef:
return new

def visit_global_decl(self, node: GlobalDecl) -> GlobalDecl:
return GlobalDecl(node.names[:])
return GlobalDecl(node.names.copy())

def visit_nonlocal_decl(self, node: NonlocalDecl) -> NonlocalDecl:
return NonlocalDecl(node.names[:])
return NonlocalDecl(node.names.copy())

def visit_block(self, node: Block) -> Block:
return Block(self.statements(node.body))
Expand Down Expand Up @@ -513,8 +513,8 @@ def visit_call_expr(self, node: CallExpr) -> CallExpr:
return CallExpr(
self.expr(node.callee),
self.expressions(node.args),
node.arg_kinds[:],
node.arg_names[:],
node.arg_kinds.copy(),
node.arg_names.copy(),
self.optional_expr(node.analyzed),
)

Expand Down
2 changes: 1 addition & 1 deletion mypyc/analysis/dataflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def cleanup_cfg(blocks: list[BasicBlock]) -> None:
# Then delete any blocks that have no predecessors
changed = False
cfg = get_cfg(blocks)
orig_blocks = blocks[:]
orig_blocks = blocks.copy()
blocks.clear()
for i, block in enumerate(orig_blocks):
if i == 0 or cfg.pred[block]:
Expand Down
2 changes: 1 addition & 1 deletion mypyc/ir/module_ir.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(
final_names: list[tuple[str, RType]],
) -> None:
self.fullname = fullname
self.imports = imports[:]
self.imports = imports.copy()
self.functions = functions
self.classes = classes
self.final_names = final_names
Expand Down
10 changes: 5 additions & 5 deletions mypyc/ir/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def __init__(self, dest: Register, src: list[Value], line: int = -1) -> None:
self.src = src

def sources(self) -> list[Value]:
return self.src[:]
return self.src.copy()

def stolen(self) -> list[Value]:
return []
Expand Down Expand Up @@ -542,7 +542,7 @@ def __init__(self, fn: FuncDecl, args: Sequence[Value], line: int) -> None:
super().__init__(line)

def sources(self) -> list[Value]:
return list(self.args[:])
return list(self.args.copy())

def accept(self, visitor: OpVisitor[T]) -> T:
return visitor.visit_call(self)
Expand Down Expand Up @@ -570,7 +570,7 @@ def __init__(self, obj: Value, method: str, args: list[Value], line: int = -1) -
super().__init__(line)

def sources(self) -> list[Value]:
return self.args[:] + [self.obj]
return self.args.copy() + [self.obj]

def accept(self, visitor: OpVisitor[T]) -> T:
return visitor.visit_method_call(self)
Expand Down Expand Up @@ -790,7 +790,7 @@ def __init__(self, items: list[Value], line: int) -> None:
self.type = self.tuple_type

def sources(self) -> list[Value]:
return self.items[:]
return self.items.copy()

def accept(self, visitor: OpVisitor[T]) -> T:
return visitor.visit_tuple_set(self)
Expand Down Expand Up @@ -1394,7 +1394,7 @@ def __init__(self, src: list[Value]) -> None:
self.src = src

def sources(self) -> list[Value]:
return self.src[:]
return self.src.copy()

def accept(self, visitor: OpVisitor[T]) -> T:
return visitor.visit_keep_alive(self)
Expand Down
4 changes: 2 additions & 2 deletions mypyc/irbuild/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ def translate_method_call(builder: IRBuilder, expr: CallExpr, callee: MemberExpr
def call_classmethod(builder: IRBuilder, ir: ClassIR, expr: CallExpr, callee: MemberExpr) -> Value:
decl = ir.method_decl(callee.name)
args = []
arg_kinds, arg_names = expr.arg_kinds[:], expr.arg_names[:]
arg_kinds, arg_names = expr.arg_kinds.copy(), expr.arg_names.copy()
# Add the class argument for class methods in extension classes
if decl.kind == FUNC_CLASSMETHOD and ir.is_ext_class:
args.append(builder.load_native_type_object(ir.fullname))
Expand Down Expand Up @@ -452,7 +452,7 @@ def translate_super_method_call(builder: IRBuilder, expr: CallExpr, callee: Supe

decl = base.method_decl(callee.name)
arg_values = [builder.accept(arg) for arg in expr.args]
arg_kinds, arg_names = expr.arg_kinds[:], expr.arg_names[:]
arg_kinds, arg_names = expr.arg_kinds.copy(), expr.arg_names.copy()

if decl.kind != FUNC_STATICMETHOD:
# Grab first argument
Expand Down
2 changes: 1 addition & 1 deletion mypyc/irbuild/ll_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ def self(self) -> Register:

def flush_keep_alives(self) -> None:
if self.keep_alives:
self.add(KeepAlive(self.keep_alives[:]))
self.add(KeepAlive(self.keep_alives.copy()))
self.keep_alives = []

# Type conversions
Expand Down
2 changes: 1 addition & 1 deletion mypyc/irbuild/prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def build_type_map(
)
class_ir.is_ext_class = is_extension_class(cdef)
if class_ir.is_ext_class:
class_ir.deletable = cdef.info.deletable_attributes[:]
class_ir.deletable = cdef.info.deletable_attributes.copy()
# If global optimizations are disabled, turn of tracking of class children
if not options.global_opts:
class_ir.children = None
Expand Down
2 changes: 1 addition & 1 deletion mypyc/transform/refcount.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def insert_ref_count_opcodes(ir: FuncIR) -> None:
defined = analyze_must_defined_regs(ir.blocks, cfg, args, values, strict_errors=True)
ordering = make_value_ordering(ir)
cache: BlockCache = {}
for block in ir.blocks[:]:
for block in ir.blocks.copy():
if isinstance(block.ops[-1], (Branch, Goto)):
insert_branch_inc_and_decrefs(
block,
Expand Down
2 changes: 1 addition & 1 deletion runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def main() -> None:
exit(1)

if not args:
args = DEFAULT_COMMANDS[:]
args = DEFAULT_COMMANDS.copy()

status = 0

Expand Down

0 comments on commit 186432d

Please sign in to comment.