diff --git a/pyiron_workflow/channels.py b/pyiron_workflow/channels.py index 04e9e9f2..64084eb6 100644 --- a/pyiron_workflow/channels.py +++ b/pyiron_workflow/channels.py @@ -652,7 +652,7 @@ def __call__(self, other: OutputSignal) -> None: self.received_signals.update([other.scoped_label]) if ( len( - set(c.scoped_label for c in self.connections).difference( + {c.scoped_label for c in self.connections}.difference( self.received_signals ) ) diff --git a/pyiron_workflow/io.py b/pyiron_workflow/io.py index 0293bb6c..5bb6f170 100644 --- a/pyiron_workflow/io.py +++ b/pyiron_workflow/io.py @@ -113,16 +113,16 @@ def __setitem__(self, key, value): def connections(self) -> list[Channel]: """All the unique connections across all channels""" return list( - set([connection for channel in self for connection in channel.connections]) + {connection for channel in self for connection in channel.connections} ) @property def connected(self): - return any([c.connected for c in self]) + return any(c.connected for c in self) @property def fully_connected(self): - return all([c.connected for c in self]) + return all(c.connected for c in self) def disconnect(self) -> list[tuple[Channel, Channel]]: """ @@ -182,11 +182,11 @@ def to_value_dict(self): def to_list(self): """A list of channel values (order not guaranteed)""" - return list(channel.value for channel in self.channel_dict.values()) + return [channel.value for channel in self.channel_dict.values()] @property def ready(self): - return all([c.ready for c in self]) + return all(c.ready for c in self) def activate_strict_hints(self): [c.activate_strict_hints() for c in self] @@ -400,9 +400,7 @@ def set_input_values(self, *args, **kwargs) -> None: f"Received {len(args)} args, but only have {len(self.inputs.labels)} " f"input channels available" ) - keyed_args = { - label: value for label, value in zip(self.inputs.labels, args, strict=False) - } + keyed_args = dict(zip(self.inputs.labels, args, strict=False)) if len(set(keyed_args.keys()).intersection(kwargs.keys())) > 0: raise ValueError( diff --git a/pyiron_workflow/mixin/preview.py b/pyiron_workflow/mixin/preview.py index 21463d4c..08c06c47 100644 --- a/pyiron_workflow/mixin/preview.py +++ b/pyiron_workflow/mixin/preview.py @@ -197,7 +197,7 @@ def _build_outputs_preview(cls): type_hints = [None] * len(labels) # Note that this nicely differs from `NoneType`, which is the hint when # `None` is actually the hint! - return {label: hint for label, hint in zip(labels, type_hints, strict=False)} + return dict(zip(labels, type_hints, strict=False)) @classmethod def _get_output_labels(cls): diff --git a/pyiron_workflow/nodes/for_loop.py b/pyiron_workflow/nodes/for_loop.py index b2b61979..af23faba 100644 --- a/pyiron_workflow/nodes/for_loop.py +++ b/pyiron_workflow/nodes/for_loop.py @@ -57,7 +57,7 @@ def dictionary_to_index_maps( nested_data_lengths = ( [] if (nested_keys is None or len(nested_keys) == 0) - else list(len(data[key]) for key in nested_keys) + else [len(data[key]) for key in nested_keys] ) except TypeError as e: raise TypeError( diff --git a/pyiron_workflow/topology.py b/pyiron_workflow/topology.py index c60c9131..e96eeb76 100644 --- a/pyiron_workflow/topology.py +++ b/pyiron_workflow/topology.py @@ -184,7 +184,7 @@ def _set_run_connections_according_to_dag(nodes: dict[str, Node]) -> list[Node]: for node in nodes.values(): upstream_connections = [con for inp in node.inputs for con in inp.connections] - upstream_nodes = set([c.owner for c in upstream_connections]) + upstream_nodes = {c.owner for c in upstream_connections} upstream_rans = [n.signals.output.ran for n in upstream_nodes] node.signals.input.accumulate_and_run.connect(*upstream_rans) # Note: We can be super fast-and-loose here because the `nodes_to_data_digraph` call @@ -225,7 +225,7 @@ def get_nodes_in_data_tree(node: Node) -> set[Node]: Get a set of all nodes from this one and upstream through data connections. """ try: - nodes = set([node]) + nodes = {node} for channel in node.inputs: for connection in channel.connections: nodes = nodes.union(get_nodes_in_data_tree(connection.owner)) diff --git a/pyiron_workflow/type_hinting.py b/pyiron_workflow/type_hinting.py index ccf15be2..f8619df0 100644 --- a/pyiron_workflow/type_hinting.py +++ b/pyiron_workflow/type_hinting.py @@ -37,18 +37,14 @@ def type_hint_to_tuple(type_hint) -> tuple: def type_hint_is_as_or_more_specific_than(hint, other) -> bool: hint_origin = typing.get_origin(hint) other_origin = typing.get_origin(other) - if set([hint_origin, other_origin]) & set([types.UnionType, typing.Union]): + if {hint_origin, other_origin} & {types.UnionType, typing.Union}: # If either hint is a union, turn both into tuples and call recursively return all( - [ - any( - [ - type_hint_is_as_or_more_specific_than(h, o) - for o in type_hint_to_tuple(other) - ] - ) - for h in type_hint_to_tuple(hint) - ] + any( + type_hint_is_as_or_more_specific_than(h, o) + for o in type_hint_to_tuple(other) + ) + for h in type_hint_to_tuple(hint) ) elif hint_origin is None and other_origin is None: # Once both are raw classes, just do a subclass test @@ -74,10 +70,8 @@ def type_hint_is_as_or_more_specific_than(hint, other) -> bool: elif len(other_args) == len(hint_args): # If they both specify arguments, they should be more specific 1:1 return all( - [ - type_hint_is_as_or_more_specific_than(h, o) - for o, h in zip(other_args, hint_args, strict=False) - ] + type_hint_is_as_or_more_specific_than(h, o) + for o, h in zip(other_args, hint_args, strict=False) ) else: # Otherwise they both specify but a mis-matching number of args @@ -85,15 +79,8 @@ def type_hint_is_as_or_more_specific_than(hint, other) -> bool: else: # Otherwise order doesn't matter so make sure the arguments are a subset return all( - [ - any( - [ - type_hint_is_as_or_more_specific_than(h, o) - for o in other_args - ] - ) - for h in hint_args - ] + any(type_hint_is_as_or_more_specific_than(h, o) for o in other_args) + for h in hint_args ) else: # Lastly, if they both have origins, but different ones, fail diff --git a/pyproject.toml b/pyproject.toml index b9b433b7..650099bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,6 +82,8 @@ select = [ "SIM", # isort "I", + # flake8-comprehensions + "C4", ] ignore = ["E501"] #ignore line-length violations diff --git a/tests/integration/test_workflow.py b/tests/integration/test_workflow.py index 16cba1c5..f1686be1 100644 --- a/tests/integration/test_workflow.py +++ b/tests/integration/test_workflow.py @@ -325,7 +325,7 @@ def test_failure(self): f"written a recovery file, so after removing that the whole " f"node directory for the workflow should be cleaned up." f"Instead, {wf.as_path()} exists and has content " - f"{[f for f in wf.as_path().iterdir()] if wf.as_path().is_dir() else None}", + f"{list(wf.as_path().iterdir()) if wf.as_path().is_dir() else None}", ) diff --git a/tests/unit/test_io.py b/tests/unit/test_io.py index 32a58a2e..00586444 100644 --- a/tests/unit/test_io.py +++ b/tests/unit/test_io.py @@ -132,7 +132,7 @@ def test_conversion(self): ) def test_iteration(self): - self.assertTrue(all([c.label in self.input.labels for c in self.input])) + self.assertTrue(all(c.label in self.input.labels for c in self.input)) def test_connections_property(self): self.assertEqual(