diff --git a/src/oedisi/componentframework/basic_component.py b/src/oedisi/componentframework/basic_component.py index 60c0557..9a97986 100644 --- a/src/oedisi/componentframework/basic_component.py +++ b/src/oedisi/componentframework/basic_component.py @@ -1,6 +1,4 @@ -""" -Generate basic component from description JSON -""" +"""Generate basic component from description JSON.""" import json import os @@ -12,7 +10,7 @@ class ComponentDescription(BaseModel): - """Component description for simple ComponentType + """Component description for simple ComponentType. Parameters ---------- @@ -45,7 +43,7 @@ def component_from_json(f, type_checker): def basic_component(comp_desc: ComponentDescription, type_checker): - """Uses data in component_definition to create a new component type + """Uses data in component_definition to create a new component type. Parameters ---------- diff --git a/src/oedisi/componentframework/mock_component.py b/src/oedisi/componentframework/mock_component.py index 5c9d34c..c3022d8 100644 --- a/src/oedisi/componentframework/mock_component.py +++ b/src/oedisi/componentframework/mock_component.py @@ -11,7 +11,7 @@ import helics as h import logging -from typing import Dict +from typing import Dict, Optional import json import os from . import system_configuration @@ -29,9 +29,9 @@ def __init__( name, parameters: Dict[str, Dict[str, str]], directory: str, - host: str = None, - port: int = None, - comp_type: str = None, + host: Optional[str] = None, + port: Optional[int] = None, + comp_type: Optional[str] = None, ): self._name = name self._directory = directory @@ -99,7 +99,7 @@ def __init__(self): self.fed = h.helicsCreateValueFederateFromConfig("helics_config.json") logger.info(f"Created federate {self.fed.name}") - with open("input_mapping.json", "r") as f: + with open("input_mapping.json") as f: port_mapping = json.load(f) self.subscriptions = {} for name, key in port_mapping.items(): diff --git a/src/oedisi/componentframework/system_configuration.py b/src/oedisi/componentframework/system_configuration.py index 39cb9a1..9b5c49d 100644 --- a/src/oedisi/componentframework/system_configuration.py +++ b/src/oedisi/componentframework/system_configuration.py @@ -27,7 +27,8 @@ class AnnotatedType(BaseModel): - "Class for representing the types of components and their interfaces" + "Class for representing the types of components and their interfaces." + type: str description: Optional[str] unit: Optional[str] @@ -105,7 +106,8 @@ def connect(self, port: "Port"): class Component(BaseModel): """Component type used in WiringDiagram, includes name, - component type, and initial parameters""" + component type, and initial parameters. + """ name: str type: str @@ -125,7 +127,8 @@ def validate_image(cls, v, values, **kwargs): class WiringDiagram(BaseModel): - "Cosimulation configuration. This may end up wrapped in another interface" + "Cosimulation configuration. This may end up wrapped in another interface." + name: str components: List[Component] links: List[Link] @@ -154,7 +157,7 @@ def clean_model(self, target_directory="."): @validator("components") def check_component_names(cls, components): - "Check that the components all have unique names" + "Check that the components all have unique names." names = set(map(lambda c: c.name, components)) assert len(names) == len(components) return components @@ -180,7 +183,8 @@ def empty(cls, name="unnamed"): class Federate(BaseModel): - "Federate configuration for HELICS CLI" + "Federate configuration for HELICS CLI." + directory: str hostname: str = "localhost" name: str @@ -200,7 +204,7 @@ def initialize_federates( compatability_checker, target_directory=".", ) -> List[Federate]: - "Initialize all the federates" + "Initialize all the federates." components = {} link_map = get_link_map(wiring_diagram) for component in wiring_diagram.components: @@ -255,7 +259,7 @@ def get_link_map(wiring_diagram: WiringDiagram): class RunnerConfig(BaseModel): - """HELICS running config for the full simulation + """HELICS running config for the full simulation. Examples -------- @@ -312,5 +316,5 @@ def generate_runner_config( exec=f"helics_broker -f {len(federates)} --loglevel=warning", ) return RunnerConfig( - name=wiring_diagram.name, federates=(federates + [broker_federate]) + name=wiring_diagram.name, federates=([*federates, broker_federate]) ) diff --git a/src/oedisi/componentframework/wiring_diagram_utils.py b/src/oedisi/componentframework/wiring_diagram_utils.py index 8054eda..20fc97e 100644 --- a/src/oedisi/componentframework/wiring_diagram_utils.py +++ b/src/oedisi/componentframework/wiring_diagram_utils.py @@ -1,16 +1,15 @@ -"""Wiring Diagram utilities +"""Wiring Diagram utilities. Wiring diagrams can be hard to manage in their final list based form. Some utilities plot, and future additions include nested wiring diagram composition and a programmatic interface. """ -from . import system_configuration from .system_configuration import WiringDiagram def get_graph(wiring_diagram: WiringDiagram): - "Get networkx graph representation of wiring_diagram" + "Get networkx graph representation of wiring_diagram." import networkx as nx g = nx.MultiDiGraph() @@ -90,7 +89,7 @@ def plot_graph_bokeh(wiring_diagram: WiringDiagram): CustomJS, ) from bokeh.layouts import layout - from bokeh.io import output_file, show + from bokeh.io import show G = get_graph(wiring_diagram) graph_renderer = get_graph_renderer(G) diff --git a/src/oedisi/tools/broker_utils.py b/src/oedisi/tools/broker_utils.py index 2b51e4b..431bab0 100644 --- a/src/oedisi/tools/broker_utils.py +++ b/src/oedisi/tools/broker_utils.py @@ -1,16 +1,16 @@ -import helics as h from pydantic import BaseModel class TimeData(BaseModel): - "Time data for a federate" + "Time data for a federate." + name: str granted_time: float send_time: float def pprint_time_data(time_data): - "A table would be better somehow, but which should be the columns" + "A table would be better somehow, but which should be the columns." print( f""" Name : {time_data.name} diff --git a/src/oedisi/tools/cli_tools.py b/src/oedisi/tools/cli_tools.py index a2e2ec7..de14761 100644 --- a/src/oedisi/tools/cli_tools.py +++ b/src/oedisi/tools/cli_tools.py @@ -38,7 +38,7 @@ def cli(): def bad_type_checker(type, x): - "Does not check types" + "Does not check types." return True @@ -88,7 +88,7 @@ def build( broker_port, node_port=30000, ): - """Build to the simulation folder + r"""Build to the simulation folder. Examples:: @@ -97,9 +97,9 @@ def build( oedisi build --component-dict components.json --system scenario.json \f + Parameters ---------- - target_directory : str (default="build") build path system : str (default="system.json") @@ -114,7 +114,7 @@ def build( The port exposed externally from k8s for external access on localhost """ click.echo(f"Loading the components defined in {component_dict}") - with open(component_dict, "r") as f: + with open(component_dict) as f: component_dict_of_files = json.load(f) component_types = { name: get_basic_component(component_file) @@ -227,12 +227,12 @@ def edit_docker_file(file_path, component: Component): with open(file_path, "w") as f: f.write(f"FROM {BASE_DOCKER_IMAGE}\n") - f.write(f"RUN apt-get update\n") - f.write(f"RUN apt-get install -y git ssh\n") + f.write("RUN apt-get update\n") + f.write("RUN apt-get install -y git ssh\n") f.write(f"RUN mkdir {component.name}\n") f.write(f"COPY . ./{component.name}\n") f.write(f"WORKDIR ./{component.name}\n") - f.write(f"RUN pip install -r requirements.txt\n") + f.write("RUN pip install -r requirements.txt\n") f.write(f"EXPOSE {component.container_port}/tcp\n") cmd = f'CMD {["python", "server.py", component.host, str(component.container_port)]}\n' cmd = cmd.replace("'", '"') @@ -252,7 +252,7 @@ def create_docker_compose_file( config = {"services": {}, "networks": {}} config["services"][f"{APP_NAME}_{BROKER_SERVICE}"] = { - "build": {"context": f"./broker/."}, + "build": {"context": "./broker/."}, "image": f"{DOCKER_HUB_USER}/{APP_NAME}_{BROKER_SERVICE}", "ports": [f"{broker_port}:{broker_port}"], "networks": {"custom-network": {"ipv4_address": "10.5.0.2"}}, @@ -293,7 +293,7 @@ def create_docker_compose_file( help="Location of helics run json. Usually build/system_runner.json", ) def run(runner): - """Calls out to helics run command + """Calls out to helics run command. Examples:: @@ -399,7 +399,7 @@ def run_mc(runner, kubernetes, docker_compose): help="Path to parameters JSON (default is parameters={})", ) def test_description(target_directory, component_desc, parameters): - """Test component intialization from component description + r"""Test component intialization from component description. Examples:: @@ -414,9 +414,9 @@ def test_description(target_directory, component_desc, parameters): \f + Parameters ---------- - target_directory : str build location @@ -435,7 +435,6 @@ def test_description(target_directory, component_desc, parameters): inputs and outputs (basically recorder federate?) Create and run system with wiring diagram """ - comp_desc = ComponentDescription.parse_file(component_desc) comp_desc.directory = os.path.dirname(component_desc) @@ -495,7 +494,7 @@ def test_description(target_directory, component_desc, parameters): def remove_from_runner_config(runner_config, element): - "Remove federate from configuration" + "Remove federate from configuration." within_feds = [fed for fed in runner_config.federates if fed.name != element] without_feds = [fed for fed in runner_config.federates if fed.name == element] new_config = RunnerConfig(name=runner_config.name, federates=within_feds) @@ -503,8 +502,8 @@ def remove_from_runner_config(runner_config, element): def remove_from_json(system_json, element): - "Remove federate from configuration and resave with revised.json" - with open(system_json, "r") as f: + "Remove federate from configuration and resave with revised.json." + with open(system_json) as f: runner_config = RunnerConfig.parse_obj(json.load(f)) new_config, without_feds = remove_from_runner_config(runner_config, element) @@ -524,17 +523,17 @@ def remove_from_json(system_json, element): ) @click.option("--foreground", type=str, help="Name of component to run in background") def debug_component(runner, foreground): - """ - Run system runner json with one component in the JSON + r""" + Run system runner json with one component in the JSON. We remove one component from system_runner.json and then call helics run in the background with our new json. and then run our debugging component in standard in / standard out. \f + Parameters ---------- - runner : str filepath to system runner json diff --git a/src/oedisi/tools/metrics.py b/src/oedisi/tools/metrics.py index 6167143..ea7eca5 100644 --- a/src/oedisi/tools/metrics.py +++ b/src/oedisi/tools/metrics.py @@ -5,7 +5,8 @@ - Mean squared relative error. For angles: -- Mean absolute angle error.""" +- Mean absolute angle error. +""" import click from pathlib import Path @@ -60,9 +61,9 @@ def evaluate_estimate(path, metric, angle_unit): - MAAE: Mean absolute angle error. \f + Parameters ---------- - path : Path Path to the folder containing the measurement files. diff --git a/src/oedisi/tools/testing_broker.py b/src/oedisi/tools/testing_broker.py index 414ae03..c184531 100644 --- a/src/oedisi/tools/testing_broker.py +++ b/src/oedisi/tools/testing_broker.py @@ -55,6 +55,6 @@ def wait_until_connected(self): current_state = self.broker.query("broker", "current_state") cores = current_state["cores"] if len(cores) == 2 and all( - (core["state"] == "init_requested" for core in cores) + core["state"] == "init_requested" for core in cores ): return diff --git a/src/oedisi/types/data_types.py b/src/oedisi/types/data_types.py index 999f92a..f488811 100644 --- a/src/oedisi/types/data_types.py +++ b/src/oedisi/types/data_types.py @@ -2,7 +2,7 @@ import datetime from enum import Enum from pydantic import BaseModel, root_validator -from typing import List, Optional, Union, Tuple +from typing import Tuple ### Supporting Functions ### # TODO: Connect with CIM values @@ -16,13 +16,13 @@ class StateArray(BaseModel): Extended by classes: "SwitchStates", "CapacitorStates", - "RegulatorStates" + "RegulatorStates". """ - values: List[int] - ids: List[str] - time: Optional[datetime.datetime] + values: list[int] + ids: list[str] + time: datetime.datetime | None class SwitchStates(StateArray): @@ -44,14 +44,14 @@ class CostArray(BaseModel): "ReactiveCostFunctions", "RealWholesalePrices", "ReactiveWholesalePrices", - "OperationalCosts" + "OperationalCosts". """ - values: List[List[float]] - ids: List[str] + values: list[list[float]] + ids: list[str] units: str = "$" - time: Optional[datetime.datetime] + time: datetime.datetime | None class RealCostFunctions(CostArray): @@ -79,15 +79,15 @@ class MeasurementArray(BaseModel): Extended by classes: "BusArray", "EquipmentArray", - "EquipmentNodeArray" + "EquipmentNodeArray". """ - values: List[float] - ids: List[str] + values: list[float] + ids: list[str] units: str - accuracy: Optional[List[float]] - bad_data_threshold: Optional[List[float]] - time: Optional[datetime.datetime] + accuracy: list[float] | None + bad_data_threshold: list[float] | None + time: datetime.datetime | None class BusArray(MeasurementArray): @@ -96,7 +96,7 @@ class BusArray(MeasurementArray): "VoltagesMagnitude", "VoltagesAngle", "VoltagesReal", - "VoltagesImaginary" + "VoltagesImaginary". """ pass @@ -116,7 +116,7 @@ class EquipmentArray(MeasurementArray): "ImpedanceMagnitude", "ImpedanceAngle", "ImpedanceReal", - "ImpedanceImaginary", + "ImpedanceImaginary". """ pass @@ -133,11 +133,11 @@ class EquipmentNodeArray(MeasurementArray): "PowersMagnitude", "PowersAngle", "PowersReal", - "PowersImaginary", + "PowersImaginary". """ - equipment_ids: List[str] + equipment_ids: list[str] class VoltagesMagnitude(BusArray): @@ -221,32 +221,32 @@ class StatesOfCharge(EquipmentArray): class Topology(BaseModel): - admittance: Union[AdmittanceSparse, AdmittanceMatrix] + admittance: AdmittanceSparse | AdmittanceMatrix injections: Injection - incidences: Optional[IncidenceList] - base_voltage_angles: Optional[VoltagesAngle] - base_voltage_magnitudes: Optional[VoltagesMagnitude] - slack_bus: List[str] = [] + incidences: IncidenceList | None = None + base_voltage_angles: VoltagesAngle | None = None + base_voltage_magnitudes: VoltagesMagnitude | None = None + slack_bus: list[str] = [] class Incidence(BaseModel): - from_equipment: List[str] - to_equipment: List[str] - equipment_type: Optional[List[str]] + from_equipment: list[str] + to_equipment: list[str] + equipment_type: list[str] | None class IncidenceList(Incidence): - ids: List[str] + ids: list[str] class AdmittanceSparse(Incidence): - admittance_list: List[Complex] + admittance_list: list[Complex] units: str = "S" class AdmittanceMatrix(BaseModel): - admittance_matrix: List[List[Complex]] - ids: List[str] + admittance_matrix: list[list[Complex]] + ids: list[str] units: str = "S" @@ -273,13 +273,13 @@ class Command(BaseModel): obj_name: str obj_property: str - val: Union[int, float, str, List[int], List[float], List[str]] + val: int | float | str | list[int] | list[float] | list[str] class CommandList(BaseModel): """List[Command] with JSON parsing.""" - __root__: List[Command] + __root__: list[Command] class ReactivePowerSetting(Enum): @@ -305,24 +305,24 @@ class VVControl(BaseModel): varchangetolerance: float = 0.025 voltagechangetolerance: float = 0.0001 vv_refreactivepower: ReactivePowerSetting = ReactivePowerSetting.VARAVAL_WATTS - voltage: List[float] # p.u. in V - reactive_response: List[float] # p.u. in VArs + voltage: list[float] # p.u. in V + reactive_response: list[float] # p.u. in VArs class VWControl(BaseModel): """OpenDSS setting for volt-watt control.""" deltap_factor: float = -1.0 # -1.0 tells OpenDSS to figure it out - voltage: List[float] # p.u. in V - power_response: List[float] # p.u. in VArs + voltage: list[float] # p.u. in V + power_response: list[float] # p.u. in VArs class InverterControl(BaseModel): """InverterControl with volt-var control and/or volt-watt control.""" - pvsystem_list: Optional[List[str]] = None - vvcontrol: Optional[VVControl] = None - vwcontrol: Optional[VWControl] = None + pvsystem_list: list[str] | None = None + vvcontrol: VVControl | None = None + vwcontrol: VWControl | None = None mode: InverterControlMode = InverterControlMode.voltvar @root_validator(pre=True) @@ -344,4 +344,4 @@ def check_mode(cls, values): class InverterControlList(BaseModel): """List[InverterControl] with JSON parsing.""" - __root__: List[InverterControl] + __root__: list[InverterControl] diff --git a/tests/test_basic_system/test_component_type/test_component_type.py b/tests/test_basic_system/test_component_type/test_component_type.py index 9fbd61c..c89f4a5 100644 --- a/tests/test_basic_system/test_component_type/test_component_type.py +++ b/tests/test_basic_system/test_component_type/test_component_type.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ """ @@ -34,7 +33,7 @@ def __init__(self): self.fed = h.helicsCreateValueFederate(self.parameters["name"], fedinfo) logger.info(f"Created federate {self.fed.name}") - with open("input_mapping.json", "r") as f: + with open("input_mapping.json") as f: port_mapping = json.load(f) self.subscriptions = {} if "test1" in port_mapping: diff --git a/tests/test_mock_system/test_system_configuration.py b/tests/test_mock_system/test_system_configuration.py index 9bb9742..503c2c9 100644 --- a/tests/test_mock_system/test_system_configuration.py +++ b/tests/test_mock_system/test_system_configuration.py @@ -3,7 +3,6 @@ WiringDiagram, ) from oedisi.componentframework.mock_component import MockComponent -import json component_types = {"MockComponent": MockComponent} wiring_diagram = WiringDiagram.parse_file("test_system.json") diff --git a/tests/unit_tests/test_oedisi_tools/broker/server.py b/tests/unit_tests/test_oedisi_tools/broker/server.py index ee78903..49626c9 100644 --- a/tests/unit_tests/test_oedisi_tools/broker/server.py +++ b/tests/unit_tests/test_oedisi_tools/broker/server.py @@ -1,6 +1,5 @@ -from fastapi import FastAPI, BackgroundTasks, UploadFile +from fastapi import FastAPI, BackgroundTasks from fastapi.exceptions import HTTPException -from fastapi.responses import FileResponse from pathlib import Path @@ -10,7 +9,6 @@ import uvicorn import logging import socket -import time import yaml import sys import os @@ -24,7 +22,7 @@ def read_settings(): component_map = {} yaml_file = BASE_PATH / "docker-compose.yml" assert yaml_file.exists(), f"{yaml_file} does not exist" - with open(yaml_file, "r") as stream: + with open(yaml_file) as stream: config = yaml.safe_load(stream) services = config["services"] print(services) @@ -46,7 +44,7 @@ def run_simulation(services, component_map, broker_ip, api_port): broker = h.helicsCreateBroker("zmq", "", initstring) logging.info(broker) isconnected = h.helicsBrokerIsConnected(broker) - logging.info(f"Broker connected: " + str(isconnected)) + logging.info("Broker connected: " + str(isconnected)) logging.info(str(component_map)) replies = [] for service_ip, service_port in component_map.items(): @@ -83,7 +81,7 @@ async def run_feeder(background_tasks: BackgroundTasks): try: data_input = read_settings() background_tasks.add_task(run_simulation, *data_input) - except Exception as e: + except Exception: err = traceback.format_exc() raise HTTPException(status_code=404, detail=str(err)) diff --git a/tests/unit_tests/test_oedisi_tools/component1/component1.py b/tests/unit_tests/test_oedisi_tools/component1/component1.py index 1a083d0..2919990 100644 --- a/tests/unit_tests/test_oedisi_tools/component1/component1.py +++ b/tests/unit_tests/test_oedisi_tools/component1/component1.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ """ from oedisi.types.common import BrokerConfig @@ -6,7 +5,6 @@ import logging import json import os -import time logger = logging.getLogger(__name__) @@ -35,7 +33,7 @@ def __init__(self, broker_config: BrokerConfig = None): self.fed = h.helicsCreateValueFederate(self.parameters["name"], fedinfo) logger.info(f"Created federate {self.fed.name}") - with open("input_mapping.json", "r") as f: + with open("input_mapping.json") as f: port_mapping = json.load(f) self.subscriptions = {} if "test1" in port_mapping: diff --git a/tests/unit_tests/test_oedisi_tools/component1/server.py b/tests/unit_tests/test_oedisi_tools/component1/server.py index a34286b..07b90bd 100644 --- a/tests/unit_tests/test_oedisi_tools/component1/server.py +++ b/tests/unit_tests/test_oedisi_tools/component1/server.py @@ -1,11 +1,8 @@ from oedisi.types.common import BrokerConfig from component1 import TestFederate from fastapi import FastAPI, BackgroundTasks -from pydantic import BaseModel -from typing import List, Dict import uvicorn import socket -import json import sys app = FastAPI() diff --git a/tests/unit_tests/test_oedisi_tools/component2/component2.py b/tests/unit_tests/test_oedisi_tools/component2/component2.py index eebc018..5263ebe 100644 --- a/tests/unit_tests/test_oedisi_tools/component2/component2.py +++ b/tests/unit_tests/test_oedisi_tools/component2/component2.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ """ from oedisi.types.common import BrokerConfig @@ -34,7 +33,7 @@ def __init__(self, broker_config: BrokerConfig = None): self.fed = h.helicsCreateValueFederate(self.parameters["name"], fedinfo) logger.info(f"Created federate {self.fed.name}") - with open("input_mapping.json", "r") as f: + with open("input_mapping.json") as f: port_mapping = json.load(f) self.subscriptions = {} if "test1" in port_mapping: diff --git a/tests/unit_tests/test_oedisi_tools/component2/server.py b/tests/unit_tests/test_oedisi_tools/component2/server.py index b44390c..302dcc1 100644 --- a/tests/unit_tests/test_oedisi_tools/component2/server.py +++ b/tests/unit_tests/test_oedisi_tools/component2/server.py @@ -1,11 +1,8 @@ from oedisi.types.common import BrokerConfig from component2 import TestFederate from fastapi import FastAPI, BackgroundTasks -from pydantic import BaseModel -from typing import List, Dict import uvicorn import socket -import json import sys app = FastAPI() diff --git a/tests/unit_tests/test_oedisi_tools/component3/component3.py b/tests/unit_tests/test_oedisi_tools/component3/component3.py index b65ca54..c4b70c3 100644 --- a/tests/unit_tests/test_oedisi_tools/component3/component3.py +++ b/tests/unit_tests/test_oedisi_tools/component3/component3.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ """ @@ -37,7 +36,7 @@ def __init__(self): logger.info(f"Created federate {self.fed.name}") time.sleep(3) - with open("input_mapping.json", "r") as f: + with open("input_mapping.json") as f: port_mapping = json.load(f) self.subscriptions = {} if "test1" in port_mapping: diff --git a/tests/unit_tests/test_oedisi_tools/test_cli.py b/tests/unit_tests/test_oedisi_tools/test_cli.py index 5e1ff02..c3aa188 100644 --- a/tests/unit_tests/test_oedisi_tools/test_cli.py +++ b/tests/unit_tests/test_oedisi_tools/test_cli.py @@ -6,7 +6,7 @@ @pytest.fixture def base_path() -> Path: - """Get the current folder of the test""" + """Get the current folder of the test.""" return Path(__file__).parent diff --git a/tests/unit_tests/test_oedisi_tools/test_multi_container.py b/tests/unit_tests/test_oedisi_tools/test_multi_container.py index bbfd46c..10c2305 100644 --- a/tests/unit_tests/test_oedisi_tools/test_multi_container.py +++ b/tests/unit_tests/test_oedisi_tools/test_multi_container.py @@ -19,7 +19,7 @@ @pytest.fixture def base_path() -> Path: - """Get the current folder of the test""" + """Get the current folder of the test.""" return Path(__file__).parent