diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index f73c54e..8326609 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -26,7 +26,9 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: 3.12 + # Pinned to 3.11: pandas 1.5.x has no cp312 wheels, so 3.12 forces a + # source build that fails on modern setuptools (no pkg_resources). + python-version: "3.11" - name: Run image uses: abatilo/actions-poetry@v3 diff --git a/pyproject.toml b/pyproject.toml index e87ebfc..4873bf6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,12 @@ click = "^8.2.1" pyyaml = "^6.0.2" +[tool.ruff.lint] +# Pin to ruff's documented default rule set so CI is stable across ruff +# versions (newer ruff enables many more rules by default otherwise). The +# codebase is clean under this set; broadening it is a separate cleanup. +select = ["E4", "E7", "E9", "F"] + [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" diff --git a/topology_optimizer/data_preparation.py b/topology_optimizer/data_preparation.py index 12f70e9..6b18dab 100644 --- a/topology_optimizer/data_preparation.py +++ b/topology_optimizer/data_preparation.py @@ -29,6 +29,14 @@ def prepare_data( ) -> Dict[str, Any]: # Remove everything that is not a replica df_nodes = df_nodes[df_nodes["node_type"] != "API_BOUNDARY"] + # Exclude reward-type-4 nodes (Type4, Type4dot1, ... Type4dot5) entirely so + # they never enter the ILP input space. The dashboard formats the value as + # e.g. "Type4dot5"; lowercasing makes the match robust to that and to the + # registry's "type4.5" form. Guarded so older CSVs without the column work. + if "node_reward_type" in df_nodes.columns: + df_nodes = df_nodes[ + ~df_nodes["node_reward_type"].fillna("").str.lower().str.startswith("type4") + ] # Preprocessing current_nodes = create_node_dataframe(df_nodes, sev_node_providers) @@ -127,4 +135,14 @@ def default_special_limits( "node_provider": {"DFINITY": (0, "eq")}, } + # Confidential (SEV) subnets do not host a DFINITY node, so override the + # default "exactly one DFINITY node per subnet" requirement. + confidential_subnets = network_topology[ + network_topology["subnet_type"] == "Confidential" + ] + for confidential_subnet_id in confidential_subnets.index: + limits[confidential_subnet_id] = { + "node_provider": {"DFINITY": (0, "eq")}, + } + return limits