From fa95f68c622a666b4d72a9d74a92ce102746ae1b Mon Sep 17 00:00:00 2001 From: Muhammad Yasirroni Date: Mon, 29 Jun 2026 18:31:09 +1000 Subject: [PATCH 1/2] add test PosixPath --- CONTRIBUTING.md | 8 ++++++++ tests/test_core.py | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b6554db..61e3234 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,6 +43,14 @@ pytest -n auto -rA --lf -c pyproject.toml --cov-report term-missing --cov=matpow pytest --lf -rA -c pyproject.toml --cov-report term-missing --cov=matpowercaseframes --nbmake ``` +For specific test only: + +```shell +pytest -n auto -rA --lf -c pyproject.toml \ + --cov-report term-missing --cov=matpowercaseframes \ + tests/test_core.py::test_to_and_read_csv +``` + ## Pre-Commit ```shell diff --git a/tests/test_core.py b/tests/test_core.py index 215e003..5b74fcb 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1,4 +1,5 @@ import os +from pathlib import Path import numpy as np import pandas as pd @@ -221,8 +222,21 @@ def test_to_and_read_xlsx(case_path, attributes, output_path, prefix, suffix): "mpc.", "_test", ), + ( + Path(CASE_PATH_CASE9), + ATTRIBUTES_CASE9, + Path("tests/results/case9_pathlib"), + "", + "", + ), + ], + ids=[ + "case9", + "case9_prefix_suffix", + "case118", + "case118_prefix_suffix", + "case9_pathlib", ], - ids=["case9", "case9_prefix_suffix", "case118", "case118_prefix_suffix"], ) def test_to_and_read_csv(case_path, attributes, output_dir, prefix, suffix): cf = CaseFrames(case_path) # read .m file From 760d1d1e7e517d50a1dee2159d0400bb40df30b2 Mon Sep 17 00:00:00 2001 From: Muhammad Yasirroni Date: Mon, 29 Jun 2026 18:45:12 +1000 Subject: [PATCH 2/2] support Path --- matpowercaseframes/core.py | 28 +++++++++++++------------ tests/results/case9_pathlib/branch.csv | 10 +++++++++ tests/results/case9_pathlib/bus.csv | 10 +++++++++ tests/results/case9_pathlib/gen.csv | 4 ++++ tests/results/case9_pathlib/gencost.csv | 4 ++++ tests/results/case9_pathlib/info.csv | 3 +++ 6 files changed, 46 insertions(+), 13 deletions(-) create mode 100644 tests/results/case9_pathlib/branch.csv create mode 100644 tests/results/case9_pathlib/bus.csv create mode 100644 tests/results/case9_pathlib/gen.csv create mode 100644 tests/results/case9_pathlib/gencost.csv create mode 100644 tests/results/case9_pathlib/info.csv diff --git a/matpowercaseframes/core.py b/matpowercaseframes/core.py index edf4c9f..9fe7726 100644 --- a/matpowercaseframes/core.py +++ b/matpowercaseframes/core.py @@ -457,11 +457,14 @@ def __init__( Args: - data (str | dict | oct2py.io.Struct | np.ndarray | None, optional): - - str: File path to MATPOWER case name, .m file, or .xlsx file. - - dict: Data from a structured dictionary. - - oct2py.io.Struct: Octave's oct2py struct. + data: + Data source. + Supported input types: + - str or os.PathLike: MATPOWER case name, .m file, .xlsx file, or CSV + directory. + - dict or oct2py.io.Struct: Structured case data. - np.ndarray: Structured NumPy array with named fields. + - None: Empty CaseFrames object. load_case_engine (object, optional): External engine used to call MATPOWER `loadcase` (e.g. Octave). Defaults to None. If None, parse data using matpowercaseframes.reader.parse_file. @@ -487,7 +490,6 @@ def __init__( FileNotFoundError: If the specified file cannot be found. """ - # TODO: support Path object super().__init__() if columns_templates is None: self.columns_templates = copy.deepcopy(COLUMNS) @@ -519,7 +521,7 @@ def _read_data( Args: - data (str | dict | np.ndarray | None, optional): + data (str | os.PathLike | dict | np.ndarray | None, optional): Data source. load_case_engine (object | None, optional): External engine for loading MATPOWER cases. @@ -537,10 +539,9 @@ def _read_data( TypeError: If data type is not supported. """ - if isinstance(data, str): - # TODO: support Path - # TYPE: str of path - path = self._get_path(data) + if isinstance(data, (str, os.PathLike)): + # TYPE: str or path-like path + path = self._get_path(os.fspath(data)) # check if path is a directory (for CSV files) if os.path.isdir(path): @@ -593,8 +594,9 @@ def _read_data( self.name = "" else: message = ( - f"Not supported source type {type(data)}. Data must be a str path to" - f" .m file, or oct2py.io.Struct, dict, or structured NumPy array." + f"Not supported source type {type(data)}. Data must be a str or" + f" path-like path to .m, .xlsx, or CSV data, or" + f" oct2py.io.Struct, dict, or structured NumPy array." ) raise TypeError(message) @@ -631,7 +633,7 @@ def _get_path(path): Args: - path (str): File path, directory path, or MATPOWER case name. + path (str): Normalized file path, directory path, or MATPOWER case name. Returns: diff --git a/tests/results/case9_pathlib/branch.csv b/tests/results/case9_pathlib/branch.csv new file mode 100644 index 0000000..91f24da --- /dev/null +++ b/tests/results/case9_pathlib/branch.csv @@ -0,0 +1,10 @@ +branch,F_BUS,T_BUS,BR_R,BR_X,BR_B,RATE_A,RATE_B,RATE_C,TAP,SHIFT,BR_STATUS,ANGMIN,ANGMAX +1,1.0,4.0,0.0,0.0576,0.0,250.0,250.0,250.0,0.0,0.0,1.0,-360.0,360.0 +2,4.0,5.0,0.017,0.092,0.158,250.0,250.0,250.0,0.0,0.0,1.0,-360.0,360.0 +3,5.0,6.0,0.039,0.17,0.358,150.0,150.0,150.0,0.0,0.0,1.0,-360.0,360.0 +4,3.0,6.0,0.0,0.0586,0.0,300.0,300.0,300.0,0.0,0.0,1.0,-360.0,360.0 +5,6.0,7.0,0.0119,0.1008,0.209,150.0,150.0,150.0,0.0,0.0,1.0,-360.0,360.0 +6,7.0,8.0,0.0085,0.072,0.149,250.0,250.0,250.0,0.0,0.0,1.0,-360.0,360.0 +7,8.0,2.0,0.0,0.0625,0.0,250.0,250.0,250.0,0.0,0.0,1.0,-360.0,360.0 +8,8.0,9.0,0.032,0.161,0.306,250.0,250.0,250.0,0.0,0.0,1.0,-360.0,360.0 +9,9.0,4.0,0.01,0.085,0.176,250.0,250.0,250.0,0.0,0.0,1.0,-360.0,360.0 diff --git a/tests/results/case9_pathlib/bus.csv b/tests/results/case9_pathlib/bus.csv new file mode 100644 index 0000000..f7a71a2 --- /dev/null +++ b/tests/results/case9_pathlib/bus.csv @@ -0,0 +1,10 @@ +bus,BUS_I,BUS_TYPE,PD,QD,GS,BS,BUS_AREA,VM,VA,BASE_KV,ZONE,VMAX,VMIN +1,1.0,3.0,0.0,0.0,0.0,0.0,1.0,1.0,0.0,345.0,1.0,1.1,0.9 +2,2.0,2.0,0.0,0.0,0.0,0.0,1.0,1.0,0.0,345.0,1.0,1.1,0.9 +3,3.0,2.0,0.0,0.0,0.0,0.0,1.0,1.0,0.0,345.0,1.0,1.1,0.9 +4,4.0,1.0,0.0,0.0,0.0,0.0,1.0,1.0,0.0,345.0,1.0,1.1,0.9 +5,5.0,1.0,90.0,30.0,0.0,0.0,1.0,1.0,0.0,345.0,1.0,1.1,0.9 +6,6.0,1.0,0.0,0.0,0.0,0.0,1.0,1.0,0.0,345.0,1.0,1.1,0.9 +7,7.0,1.0,100.0,35.0,0.0,0.0,1.0,1.0,0.0,345.0,1.0,1.1,0.9 +8,8.0,1.0,0.0,0.0,0.0,0.0,1.0,1.0,0.0,345.0,1.0,1.1,0.9 +9,9.0,1.0,125.0,50.0,0.0,0.0,1.0,1.0,0.0,345.0,1.0,1.1,0.9 diff --git a/tests/results/case9_pathlib/gen.csv b/tests/results/case9_pathlib/gen.csv new file mode 100644 index 0000000..311596a --- /dev/null +++ b/tests/results/case9_pathlib/gen.csv @@ -0,0 +1,4 @@ +gen,GEN_BUS,PG,QG,QMAX,QMIN,VG,MBASE,GEN_STATUS,PMAX,PMIN,PC1,PC2,QC1MIN,QC1MAX,QC2MIN,QC2MAX,RAMP_AGC,RAMP_10,RAMP_30,RAMP_Q,APF +1,1.0,72.3,27.03,300.0,-300.0,1.04,100.0,1.0,250.0,10.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +2,2.0,163.0,6.54,300.0,-300.0,1.025,100.0,1.0,300.0,10.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +3,3.0,85.0,-10.95,300.0,-300.0,1.025,100.0,1.0,270.0,10.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 diff --git a/tests/results/case9_pathlib/gencost.csv b/tests/results/case9_pathlib/gencost.csv new file mode 100644 index 0000000..9458641 --- /dev/null +++ b/tests/results/case9_pathlib/gencost.csv @@ -0,0 +1,4 @@ +gen,MODEL,STARTUP,SHUTDOWN,NCOST,C2,C1,C0 +1,2.0,1500.0,0.0,3.0,0.11,5.0,150.0 +2,2.0,2000.0,0.0,3.0,0.085,1.2,600.0 +3,2.0,3000.0,0.0,3.0,0.1225,1.0,335.0 diff --git a/tests/results/case9_pathlib/info.csv b/tests/results/case9_pathlib/info.csv new file mode 100644 index 0000000..ab71732 --- /dev/null +++ b/tests/results/case9_pathlib/info.csv @@ -0,0 +1,3 @@ +,INFO +version,2 +baseMVA,100