From 324840c52e17d9b576eda0ddc20a21ae6927692c Mon Sep 17 00:00:00 2001 From: Craig <3979063+craig8@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:55:45 -0800 Subject: [PATCH 1/3] Apply ruff formatting to Python source and test files Run ruff format to normalize quote style to double quotes, wrap long lines, and fix spacing across goss.py, field_proxy_forwarder.py, and test_simulation.py. --- .../field_interface/field_proxy_forwarder.py | 3 +- gridappsd-python-lib/gridappsd/goss.py | 9 +- gridappsd-python-lib/tests/test_simulation.py | 118 +++++++++--------- 3 files changed, 68 insertions(+), 62 deletions(-) diff --git a/gridappsd-field-bus-lib/gridappsd_field_bus/field_interface/field_proxy_forwarder.py b/gridappsd-field-bus-lib/gridappsd_field_bus/field_interface/field_proxy_forwarder.py index eac4537..0bd7412 100644 --- a/gridappsd-field-bus-lib/gridappsd_field_bus/field_interface/field_proxy_forwarder.py +++ b/gridappsd-field-bus-lib/gridappsd_field_bus/field_interface/field_proxy_forwarder.py @@ -6,7 +6,8 @@ try: from importlib.metadata import version as _pkg_version - _STOMP_V8 = int(_pkg_version('stomp-py').split('.')[0]) >= 8 + + _STOMP_V8 = int(_pkg_version("stomp-py").split(".")[0]) >= 8 except Exception: _STOMP_V8 = False diff --git a/gridappsd-python-lib/gridappsd/goss.py b/gridappsd-python-lib/gridappsd/goss.py index a5921c6..503b046 100644 --- a/gridappsd-python-lib/gridappsd/goss.py +++ b/gridappsd-python-lib/gridappsd/goss.py @@ -67,10 +67,15 @@ _log: Logger = logging.getLogger(inspect.getmodulename(__file__)) # stomp.py 8.x changed listener callbacks from (headers, body) to (frame) -_stomp_major = int(getattr(_stomp_module, '__version__', (0,))[0]) if isinstance(getattr(_stomp_module, '__version__', None), tuple) else 0 +_stomp_major = ( + int(getattr(_stomp_module, "__version__", (0,))[0]) + if isinstance(getattr(_stomp_module, "__version__", None), tuple) + else 0 +) try: from importlib.metadata import version as _pkg_version - _stomp_major = int(_pkg_version('stomp-py').split('.')[0]) + + _stomp_major = int(_pkg_version("stomp-py").split(".")[0]) except Exception: pass _STOMP_V8 = _stomp_major >= 8 diff --git a/gridappsd-python-lib/tests/test_simulation.py b/gridappsd-python-lib/tests/test_simulation.py index 5861128..7c63838 100644 --- a/gridappsd-python-lib/tests/test_simulation.py +++ b/gridappsd-python-lib/tests/test_simulation.py @@ -1,64 +1,64 @@ -#import json -#import logging -#import os -#import sys -#import time -#import pytest -#from datetime import datetime, timezone +import json +import logging +import os +import sys +import time +import pytest +from datetime import datetime, timezone -#logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) +logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) -#from gridappsd import GridAPPSD, topics as t -#from gridappsd.simulation import Simulation, PowerSystemConfig, SimulationArgs, SimulationConfig +from gridappsd import GridAPPSD, topics as t +from gridappsd.simulation import Simulation, PowerSystemConfig, SimulationArgs, SimulationConfig -#simulation_is_complete = False -#measurements_received = 0 +simulation_is_complete = False +measurements_received = 0 -#@pytest.fixture -#def createGadObject(): -# gad_user = os.environ.get('GRIDAPPSD_USER') -# if gad_user is None: -# os.environ['GRIDAPPSD_USER'] = 'system' -# gad_password = os.environ.get('GRIDAPPSD_PASSWORD') -# if gad_password is None: -# os.environ['GRIDAPPSD_PASSWORD'] = 'manager' -# return GridAPPSD() +@pytest.fixture +def createGadObject(): + gad_user = os.environ.get('GRIDAPPSD_USER') + if gad_user is None: + os.environ['GRIDAPPSD_USER'] = 'system' + gad_password = os.environ.get('GRIDAPPSD_PASSWORD') + if gad_password is None: + os.environ['GRIDAPPSD_PASSWORD'] = 'manager' + return GridAPPSD() -#def test_createSimulations(createGadObject): -# gadObj = createGadObject -# response = gadObj.query_model_info() -# models = response.get("data", {}).get("models", {}) -# start_time = int(datetime(year=2025, month=1, day=1, hour=0, minute=0, second=0, microsecond=0, tzinfo=timezone.utc).timestamp()) -# simulationArgs = SimulationArgs(start_time=f"{start_time}", -# duration="120", -# run_realtime=False, -# pause_after_measurements=False) -# sim_config = SimulationConfig(simulation_config=simulationArgs) -# modelsToRun = [ -# "49AD8E07-3BF9-A4E2-CB8F-C3722F837B62", # IEEE 13 Node Test Feeder -# "C1C3E687-6FFD-C753-582B-632A27E28507" # IEEE 123 Node Test Feeder -# ] -# for m in models: -# if m.get("modelId") not in modelsToRun: -# continue -# line_name = m.get("modelId") -# subregion_name = m.get("subRegionId") -# region_name = m.get("regionId") -# psc = PowerSystemConfig(Line_name=line_name, -# SubGeographicalRegion_name=subregion_name, -# GeographicalRegion_name=region_name) -# sim_config.power_system_configs.append(psc) -# sim_obj = Simulation(gapps=gadObj, run_config=sim_config) -# def on_measurement(sim, ts, m): -# global measurements_received -# measurements_received += 1 -# def on_simulation_complete(sim): -# global simulation_is_complete -# simulation_is_complete = True -# sim_obj.add_onmeasurement_callback(on_measurement) -# sim_obj.add_oncomplete_callback(on_simulation_complete) -# sim_obj.start_simulation() -# while not simulation_is_complete: -# time.sleep(1) -# assert measurements_received == 1 -# gadObj.disconnect() +def test_createSimulations(createGadObject): + gadObj = createGadObject + response = gadObj.query_model_info() + models = response.get("data", {}).get("models", {}) + start_time = int(datetime(year=2025, month=1, day=1, hour=0, minute=0, second=0, microsecond=0, tzinfo=timezone.utc).timestamp()) + simulationArgs = SimulationArgs(start_time=f"{start_time}", + duration="120", + run_realtime=False, + pause_after_measurements=False) + sim_config = SimulationConfig(simulation_config=simulationArgs) + modelsToRun = [ + "49AD8E07-3BF9-A4E2-CB8F-C3722F837B62", # IEEE 13 Node Test Feeder + "C1C3E687-6FFD-C753-582B-632A27E28507" # IEEE 123 Node Test Feeder + ] + for m in models: + if m.get("modelId") not in modelsToRun: + continue + line_name = m.get("modelId") + subregion_name = m.get("subRegionId") + region_name = m.get("regionId") + psc = PowerSystemConfig(Line_name=line_name, + SubGeographicalRegion_name=subregion_name, + GeographicalRegion_name=region_name) + sim_config.power_system_configs.append(psc) + sim_obj = Simulation(gapps=gadObj, run_config=sim_config) + def on_measurement(sim, ts, m): + global measurements_received + measurements_received += 1 + def on_simulation_complete(sim): + global simulation_is_complete + simulation_is_complete = True + sim_obj.add_onmeasurement_callback(on_measurement) + sim_obj.add_oncomplete_callback(on_simulation_complete) + sim_obj.start_simulation() + while not simulation_is_complete: + time.sleep(1) + assert measurements_received == 1 + gadObj.disconnect() From aebf5fb59f877fc78f59e29f9269f74dc7f407d4 Mon Sep 17 00:00:00 2001 From: Craig <3979063+craig8@users.noreply.github.com> Date: Wed, 18 Feb 2026 12:01:10 -0800 Subject: [PATCH 2/3] Fix CI failures: mark integration test and resolve mypy attr-defined errors Add @pytest.mark.integration to test_createSimulations so it is skipped in CI where no STOMP broker is available. Fix mypy attr-defined errors in field_proxy_forwarder.py by extracting mRID with a type ignore. --- .../field_interface/field_proxy_forwarder.py | 5 +++-- gridappsd-python-lib/tests/test_simulation.py | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gridappsd-field-bus-lib/gridappsd_field_bus/field_interface/field_proxy_forwarder.py b/gridappsd-field-bus-lib/gridappsd_field_bus/field_interface/field_proxy_forwarder.py index 0bd7412..b575efc 100644 --- a/gridappsd-field-bus-lib/gridappsd_field_bus/field_interface/field_proxy_forwarder.py +++ b/gridappsd-field-bus-lib/gridappsd_field_bus/field_interface/field_proxy_forwarder.py @@ -103,8 +103,9 @@ def __init__(self, connection_url: str, username: str, password: str, mrid: str) self.network.get_all_edges(cim.Substation) for substation in self.network.graph.get(cim.Substation, {}).values(): - print(f"Subscribing to Substation: /topic/goss.gridappsd.field.{substation.mRID}") - self.ot_connection.subscribe("/topic/goss.gridappsd.field." + substation.mRID, self.on_message_from_ot) + mrid = substation.mRID # type: ignore[attr-defined] + print(f"Subscribing to Substation: /topic/goss.gridappsd.field.{mrid}") + self.ot_connection.subscribe("/topic/goss.gridappsd.field." + mrid, self.on_message_from_ot) # self.ot_connection.subscribe(topics.BASE_FIELD_TOPIC, self.on_message_from_ot) diff --git a/gridappsd-python-lib/tests/test_simulation.py b/gridappsd-python-lib/tests/test_simulation.py index 7c63838..47dcceb 100644 --- a/gridappsd-python-lib/tests/test_simulation.py +++ b/gridappsd-python-lib/tests/test_simulation.py @@ -24,6 +24,7 @@ def createGadObject(): os.environ['GRIDAPPSD_PASSWORD'] = 'manager' return GridAPPSD() +@pytest.mark.integration def test_createSimulations(createGadObject): gadObj = createGadObject response = gadObj.query_model_info() From 04c8da0f192fb31fedb76301e717eff780ae751c Mon Sep 17 00:00:00 2001 From: Craig <3979063+craig8@users.noreply.github.com> Date: Wed, 18 Feb 2026 12:03:00 -0800 Subject: [PATCH 3/3] Exclude integration tests from default test and coverage tasks Add -m 'not integration' to pixi test and test-cov tasks so tests requiring a running GridAPPS-D instance are skipped in CI. --- pixi.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pixi.toml b/pixi.toml index 8afc2b9..d7d6176 100644 --- a/pixi.toml +++ b/pixi.toml @@ -84,8 +84,8 @@ py314 = { features = ["dev", "py314"], solve-group = "py314" } # ────────────────────────────────────────────────────────────────────────────── # Testing # ────────────────────────────────────────────────────────────────────────────── -test = { cmd = "pytest gridappsd-python-lib/tests -v", description = "Run main library tests" } -test-cov = { cmd = "pytest gridappsd-python-lib/tests -v --cov=gridappsd --cov-report=term-missing --cov-report=html", description = "Run tests with coverage" } +test = { cmd = "pytest gridappsd-python-lib/tests -v -m 'not integration'", description = "Run main library tests" } +test-cov = { cmd = "pytest gridappsd-python-lib/tests -v -m 'not integration' --cov=gridappsd --cov-report=term-missing --cov-report=html", description = "Run tests with coverage" } test-field-bus = { cmd = "pytest gridappsd-field-bus-lib/tests -v", description = "Run field bus tests" } test-all = { depends-on = ["test", "test-field-bus"], description = "Run all tests" } test-integration = { cmd = "pytest gridappsd-python-lib/tests -v -m integration", description = "Run integration tests only" }