diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 553578a69..a513cc9f5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.14.10 + rev: v0.15.12 hooks: # Run the linter - id: ruff-check @@ -28,12 +28,12 @@ repos: - id: ruff-format - repo: https://github.com/RobertCraigie/pyright-python - rev: v1.1.407 + rev: v1.1.409 hooks: - id: pyright additional_dependencies: [types-PyYAML] - repo: https://github.com/twisted/towncrier - rev: 24.8.0 + rev: 25.8.0 hooks: - id: towncrier-check diff --git a/profiling/gprof2dot b/profiling/gprof2dot index f63368588..d48b16e56 100755 --- a/profiling/gprof2dot +++ b/profiling/gprof2dot @@ -1367,7 +1367,7 @@ class AXEParser(Parser): attrs[name] = value return Struct(attrs) - _cg_header_re = re.compile("^Index |" "^-----+ ") + _cg_header_re = re.compile("^Index |^-----+ ") _cg_footer_re = re.compile(r"^Index\s+Function\s*$") diff --git a/test/test_big_phi_robust.py b/test/test_big_phi_robust.py index 84b1db6ed..563385b26 100644 --- a/test/test_big_phi_robust.py +++ b/test/test_big_phi_robust.py @@ -175,17 +175,17 @@ def test_sia_standard_example_has_repertoires(self, s): # Check cause repertoire exists and has required attributes assert result.cause is not None, "SIA missing cause repertoire" assert hasattr(result.cause, "phi"), "Cause RIA missing phi attribute" - assert hasattr( - result.cause, "mechanism" - ), "Cause RIA missing mechanism attribute" + assert hasattr(result.cause, "mechanism"), ( + "Cause RIA missing mechanism attribute" + ) assert hasattr(result.cause, "purview"), "Cause RIA missing purview attribute" # Check effect repertoire exists and has required attributes assert result.effect is not None, "SIA missing effect repertoire" assert hasattr(result.effect, "phi"), "Effect RIA missing phi attribute" - assert hasattr( - result.effect, "mechanism" - ), "Effect RIA missing mechanism attribute" + assert hasattr(result.effect, "mechanism"), ( + "Effect RIA missing mechanism attribute" + ) assert hasattr(result.effect, "purview"), "Effect RIA missing purview attribute" def test_sia_standard_example_has_system_state(self, s): @@ -242,9 +242,9 @@ def test_sia_standard_example_partition_type(self, s): # System has phi > 0, so should have non-null partition assert result.phi > 0, "Standard example should have phi > 0" - assert not isinstance( - result.partition, NullCut - ), "Irreducible system has NullCut partition" + assert not isinstance(result.partition, NullCut), ( + "Irreducible system has NullCut partition" + ) def test_reducible_system_has_null_partition(self, reducible): """Reducible system should have null partition. @@ -254,12 +254,12 @@ def test_reducible_system_has_null_partition(self, reducible): """ result = reducible.sia() - assert isinstance( - result, NullSystemIrreducibilityAnalysis - ), "Reducible system should return NullSIA" - assert isinstance( - result.partition, NullCut - ), "Reducible system should have NullCut partition" + assert isinstance(result, NullSystemIrreducibilityAnalysis), ( + "Reducible system should return NullSIA" + ) + assert isinstance(result.partition, NullCut), ( + "Reducible system should have NullCut partition" + ) assert result.phi == 0.0, "Reducible system should have phi=0" def test_empty_subsystem_has_null_partition(self, s_empty): @@ -270,12 +270,12 @@ def test_empty_subsystem_has_null_partition(self, s_empty): """ result = s_empty.sia() - assert isinstance( - result, NullSystemIrreducibilityAnalysis - ), "Empty subsystem should return NullSIA" - assert isinstance( - result.partition, NullCut - ), "Empty subsystem should have NullCut partition" + assert isinstance(result, NullSystemIrreducibilityAnalysis), ( + "Empty subsystem should return NullSIA" + ) + assert isinstance(result.partition, NullCut), ( + "Empty subsystem should have NullCut partition" + ) assert result.phi == 0.0, "Empty subsystem should have phi=0" @@ -419,14 +419,18 @@ def _noisy_copy_subsystem(p, state): Each node copies the other with probability p (LOLI state ordering). """ import numpy as np - from pyphi import Network, Subsystem - - tpm = np.array([ - [1 - p, 1 - p], # (0,0) - [1 - p, p], # (1,0) - [p, 1 - p], # (0,1) - [p, p], # (1,1) - ]) + + from pyphi import Network + from pyphi import Subsystem + + tpm = np.array( + [ + [1 - p, 1 - p], # (0,0) + [1 - p, p], # (1,0) + [p, 1 - p], # (0,1) + [p, p], # (1,1) + ] + ) cm = np.array([[0, 1], [1, 0]]) network = Network(tpm, cm=cm, node_labels=["A", "B"]) return Subsystem(network, state) @@ -438,7 +442,8 @@ def test_phi_capped_by_ii(self): so ii(s) ≈ 0.644 caps phi below GID(MIP). """ from pyphi.direction import Direction - from pyphi.new_big_phi import sia, system_intrinsic_information + from pyphi.new_big_phi import sia + from pyphi.new_big_phi import system_intrinsic_information subsystem = self._noisy_copy_subsystem(0.8, (1, 1)) with config.override(**self.II_CONFIG): @@ -494,9 +499,7 @@ def test_gid_distance_unaffected(self, s): # Default config uses GENERALIZED_INTRINSIC_DIFFERENCE result = sia(s) - assert float(result.phi) == pytest.approx( - EXPECTED_PHI_VALUES["s"], abs=1e-9 - ) + assert float(result.phi) == pytest.approx(EXPECTED_PHI_VALUES["s"], abs=1e-9) # ============================================================================ @@ -522,7 +525,9 @@ class TestPaperExamples: def _monad_subsystem(p): """Single-node system that stays in current state with probability p.""" import numpy as np - from pyphi import Network, Subsystem + + from pyphi import Network + from pyphi import Subsystem tpm = np.array([[1 - p], [p]]) cm = np.array([[1]]) @@ -536,6 +541,7 @@ def test_monad_intrinsic_information(self): The paper reports φ_s = 0.427 (Figure 2C). """ import numpy as np + from pyphi.new_big_phi import system_intrinsic_information p = 0.744 @@ -557,8 +563,8 @@ def test_monad_intrinsic_information(self): "p,i_diff_expected,i_spec_expected", [ (0.744, 0.426625, 0.426591), # crossover point (Figure 2C) - (0.9, 0.152003, 0.763197), # high determinism - (0.6, 0.736966, 0.157821), # high noise + (0.9, 0.152003, 0.763197), # high determinism + (0.6, 0.736966, 0.157821), # high noise ], ) def test_monad_i_diff_i_spec_tradeoff(self, p, i_diff_expected, i_spec_expected): @@ -566,8 +572,8 @@ def test_monad_i_diff_i_spec_tradeoff(self, p, i_diff_expected, i_spec_expected) i_diff = -log2(p), i_spec = p*log2(2p) for a monad in its ON state. """ - import numpy as np - from pyphi import direction, metrics + from pyphi import direction + from pyphi import metrics from pyphi.new_big_phi import system_intrinsic_information subsystem = self._monad_subsystem(p) diff --git a/test/test_iit4_robust.py b/test/test_iit4_robust.py index f75f56629..31c63fda4 100644 --- a/test/test_iit4_robust.py +++ b/test/test_iit4_robust.py @@ -195,9 +195,9 @@ def test_phi_structure_has_distinctions_attribute(self, example_name): subsystem = EXAMPLES["subsystem"][example_name]() result = new_big_phi.phi_structure(subsystem) - assert hasattr( - result, "distinctions" - ), f"PhiStructure for '{example_name}' missing 'distinctions' attribute" + assert hasattr(result, "distinctions"), ( + f"PhiStructure for '{example_name}' missing 'distinctions' attribute" + ) @pytest.mark.parametrize( "example_name", @@ -227,9 +227,9 @@ def test_phi_structure_has_relations_attribute(self, example_name): subsystem = EXAMPLES["subsystem"][example_name]() result = new_big_phi.phi_structure(subsystem) - assert hasattr( - result, "relations" - ), f"PhiStructure for '{example_name}' missing 'relations' attribute" + assert hasattr(result, "relations"), ( + f"PhiStructure for '{example_name}' missing 'relations' attribute" + ) @pytest.mark.parametrize( "example_name", @@ -255,9 +255,9 @@ def test_phi_structure_distinctions_are_non_empty(self, example_name): subsystem = EXAMPLES["subsystem"][example_name]() result = new_big_phi.phi_structure(subsystem) - assert hasattr( - result, "distinctions" - ), "PhiStructure missing distinctions attribute" + assert hasattr(result, "distinctions"), ( + "PhiStructure missing distinctions attribute" + ) distinctions = result.distinctions assert distinctions is not None, ( @@ -310,9 +310,9 @@ def test_distinctions_have_mechanism_attribute(self): # Check each distinction has a mechanism for i, distinction in enumerate(concepts): - assert hasattr( - distinction, "mechanism" - ), f"Distinction {i} missing 'mechanism' attribute" + assert hasattr(distinction, "mechanism"), ( + f"Distinction {i} missing 'mechanism' attribute" + ) def test_distinctions_mechanisms_are_within_subsystem(self): """Distinction mechanisms should be subsets of subsystem nodes. diff --git a/test/test_invariants.py b/test/test_invariants.py index 121ca0576..70d5e5e87 100644 --- a/test/test_invariants.py +++ b/test/test_invariants.py @@ -158,21 +158,21 @@ def test_sia_partition_attribute_consistency(self, s, micro_s, reducible): # Irreducible systems with phi > 0 should have non-null partitions s_result = s.sia() if s_result.phi > 0: - assert not isinstance( - s_result.partition, NullCut - ), "System with phi > 0 has NullCut partition (should have real partition)" + assert not isinstance(s_result.partition, NullCut), ( + "System with phi > 0 has NullCut partition (should have real partition)" + ) micro_result = micro_s.sia() if micro_result.phi > 0: - assert not isinstance( - micro_result.partition, NullCut - ), "System with phi > 0 has NullCut partition (should have real partition)" + assert not isinstance(micro_result.partition, NullCut), ( + "System with phi > 0 has NullCut partition (should have real partition)" + ) # Reducible system should have null partition reducible_result = reducible.sia() - assert isinstance( - reducible_result.partition, NullCut - ), "Reducible system should have NullCut partition" + assert isinstance(reducible_result.partition, NullCut), ( + "Reducible system should have NullCut partition" + ) def test_partition_reduces_or_maintains_phi(self, s, micro_s): """Partitioned system cannot have more phi than unpartitioned. @@ -222,9 +222,9 @@ def test_selfloop_phi_depends_on_config(self, noisy_selfloop_single): # With config disabled, phi should be 0 with config.override(SINGLE_MICRO_NODES_WITH_SELFLOOPS_HAVE_PHI=False): result_disabled = noisy_selfloop_single.sia() - assert ( - result_disabled.phi == 0.0 - ), "Expected phi=0 when SINGLE_MICRO_NODES_WITH_SELFLOOPS_HAVE_PHI=False" + assert result_disabled.phi == 0.0, ( + "Expected phi=0 when SINGLE_MICRO_NODES_WITH_SELFLOOPS_HAVE_PHI=False" + ) # With config enabled and EMD, phi should be > 0 with config.override( @@ -253,9 +253,9 @@ def test_cache_clearing_option(self, s): CACHE_REPERTOIRES=True, ): _ = s.sia() - assert ( - s._repertoire_cache.cache - ), "Cache should have entries when clearing is disabled" + assert s._repertoire_cache.cache, ( + "Cache should have entries when clearing is disabled" + ) # Test with cache clearing enabled with config.override( @@ -264,9 +264,9 @@ def test_cache_clearing_option(self, s): CACHE_REPERTOIRES=True, ): _ = s.sia() - assert ( - not s._repertoire_cache.cache - ), "Cache should be empty when clearing is enabled" + assert not s._repertoire_cache.cache, ( + "Cache should be empty when clearing is enabled" + ) class TestPhiStructureInvariants: @@ -293,12 +293,12 @@ def test_phi_structure_has_distinctions(self, example_name): # Systems that have phi should have distinctions if hasattr(result, "phi") and result.phi > 0: - assert hasattr( - result, "distinctions" - ), f"System '{example_name}' has phi > 0 but no distinctions attribute" - assert ( - len(result.distinctions) > 0 - ), f"System '{example_name}' has phi > 0 but zero distinctions" + assert hasattr(result, "distinctions"), ( + f"System '{example_name}' has phi > 0 but no distinctions attribute" + ) + assert len(result.distinctions) > 0, ( + f"System '{example_name}' has phi > 0 but zero distinctions" + ) @pytest.mark.parametrize("example_name", ["basic", "fig4"]) def test_phi_structure_has_relations(self, example_name):