Skip to content

Commit 9bbd299

Browse files
committed
Merge branch 'feature/downloader' of github.com:alliander-opensource/power-grid-model-io into feature/downloader
2 parents dc73d0e + 5f8f32a commit 9bbd299

File tree

4 files changed

+117
-3
lines changed

4 files changed

+117
-3
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# SPDX-FileCopyrightText: 2022 Contributors to the Power Grid Model IO project <dynamic.grid.calculation@alliander.com>
2+
#
3+
# SPDX-License-Identifier: MPL-2.0
4+
"""
5+
CSV Directory Store
6+
"""
7+
8+
from pathlib import Path
9+
from typing import Any, Dict, List
10+
11+
import pandas as pd
12+
13+
from power_grid_model_io.data_stores.base_data_store import BaseDataStore
14+
from power_grid_model_io.data_types import LazyDataFrame, TabularData
15+
16+
17+
class CsvDirStore(BaseDataStore[TabularData]):
18+
"""
19+
CSV Directory Store
20+
21+
The first row of each .csv file is expected to contain the column names, unless specified differently by an
22+
extension of this class.
23+
"""
24+
25+
__slots__ = ("_dir_path", "_csv_kwargs", "_header_rows")
26+
27+
def __init__(self, dir_path: Path, **csv_kwargs):
28+
super().__init__()
29+
self._dir_path = Path(dir_path)
30+
self._csv_kwargs: Dict[str, Any] = csv_kwargs
31+
self._header_rows: List[int] = [0]
32+
33+
def load(self) -> TabularData:
34+
"""
35+
Create a lazy loader for all CSV files in a directory and store them in a TabularData instance.
36+
"""
37+
38+
def lazy_csv_loader(csv_path: Path) -> LazyDataFrame:
39+
def csv_loader():
40+
return pd.read_csv(filepath_or_buffer=csv_path, header=self._header_rows, **self._csv_kwargs)
41+
42+
return csv_loader
43+
44+
data: Dict[str, LazyDataFrame] = {}
45+
for path in self._dir_path.glob("*.csv"):
46+
data[path.stem] = lazy_csv_loader(path)
47+
48+
return TabularData(**data)
49+
50+
def save(self, data: TabularData) -> None:
51+
"""
52+
Store each table in data as a separate CSV file
53+
"""
54+
for table_name, table_data in data.items():
55+
table_data.to_csv(path_or_buf=self._dir_path / f"{table_name}.csv", **self._csv_kwargs)

src/power_grid_model_io/data_stores/excel_file_store.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
import pandas as pd
1313

1414
from power_grid_model_io.data_stores.base_data_store import BaseDataStore
15-
from power_grid_model_io.data_types import TabularData
16-
from power_grid_model_io.data_types.tabular_data import LazyDataFrame
15+
from power_grid_model_io.data_types import LazyDataFrame, TabularData
1716

1817

1918
class ExcelFileStore(BaseDataStore[TabularData]):

src/power_grid_model_io/data_types/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
"""
77

88
from power_grid_model_io.data_types._data_types import ExtraInfo, ExtraInfoLookup, StructuredData
9-
from power_grid_model_io.data_types.tabular_data import TabularData
9+
from power_grid_model_io.data_types.tabular_data import LazyDataFrame, TabularData
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# SPDX-FileCopyrightText: 2022 Contributors to the Power Grid Model project <dynamic.grid.calculation@alliander.com>
2+
#
3+
# SPDX-License-Identifier: MPL-2.0
4+
5+
import tempfile
6+
from pathlib import Path
7+
from unittest.mock import MagicMock, patch
8+
9+
import pandas as pd
10+
import pytest
11+
12+
from power_grid_model_io.data_stores.csv_dir_store import CsvDirStore
13+
from power_grid_model_io.data_types import TabularData
14+
15+
16+
@pytest.fixture()
17+
def temp_dir():
18+
with tempfile.TemporaryDirectory() as tmp:
19+
yield Path(tmp).resolve()
20+
21+
22+
def touch(file_path: Path):
23+
open(file_path, "wb").close()
24+
25+
26+
@patch("power_grid_model_io.data_stores.csv_dir_store.pd.read_csv")
27+
def test_load(mock_read_csv: MagicMock, temp_dir: Path):
28+
# Arrange
29+
foo_data = MagicMock()
30+
bar_data = MagicMock()
31+
touch(temp_dir / "foo.csv")
32+
touch(temp_dir / "bar.csv")
33+
mock_read_csv.side_effect = (foo_data, bar_data)
34+
csv_dir = CsvDirStore(temp_dir, bla=True)
35+
36+
# Act
37+
csv_data = csv_dir.load()
38+
39+
# Assert
40+
mock_read_csv.assert_not_called() # The csv data is not yet loaded
41+
assert csv_data["foo"] == foo_data
42+
assert csv_data["bar"] == bar_data
43+
mock_read_csv.assert_any_call(filepath_or_buffer=temp_dir / "foo.csv", header=[0], bla=True)
44+
mock_read_csv.assert_any_call(filepath_or_buffer=temp_dir / "bar.csv", header=[0], bla=True)
45+
46+
47+
@patch("power_grid_model_io.data_stores.csv_dir_store.pd.DataFrame.to_csv")
48+
def test_save(mock_to_csv: MagicMock, temp_dir):
49+
# Arrange
50+
foo_data = pd.DataFrame()
51+
bar_data = pd.DataFrame()
52+
data = TabularData(foo=foo_data, bar=bar_data)
53+
csv_dir = CsvDirStore(temp_dir, bla=True)
54+
55+
# Act
56+
csv_dir.save(data)
57+
58+
# Assert
59+
mock_to_csv.assert_any_call(path_or_buf=temp_dir / "foo.csv", bla=True)
60+
mock_to_csv.assert_any_call(path_or_buf=temp_dir / "bar.csv", bla=True)

0 commit comments

Comments
 (0)