Skip to content

Commit

Permalink
feat: Allow arguments of type pathlib.Path for file I/O methods (#228)
Browse files Browse the repository at this point in the history
Closes #146 .

### Summary of Changes

Changed type hints and docstrings for
* `Table.from_csv_file`
* `Table.to_csv_file`
* `Table.from_json_file`
* `Table.to_json_file`
* `Image.from_jpeg_file`
* `Image.to_jpeg_file`
* `Image.from_png_file`
* `Image.to_png_file`
* `resolve_resource_path`

to also accept arguments with type `Path`.

Updated tests accordingly.

---------

Co-authored-by: robmeth <91134475+robmeth@users.noreply.github.com>
Co-authored-by: zzril <>
Co-authored-by: megalinter-bot <129584137+megalinter-bot@users.noreply.github.com>
Co-authored-by: Lars Reimann <mail@larsreimann.com>
  • Loading branch information
4 people committed Apr 21, 2023
1 parent 7f6c3bd commit 2b58c82
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 38 deletions.
16 changes: 8 additions & 8 deletions src/safeds/data/image/containers/_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ class Image:
"""

@staticmethod
def from_jpeg_file(path: str) -> Image:
def from_jpeg_file(path: str | Path) -> Image:
"""
Create an image from a JPEG file.
Parameters
----------
path : str
path : str | Path
The path to the JPEG file.
Returns
Expand All @@ -41,13 +41,13 @@ def from_jpeg_file(path: str) -> Image:
)

@staticmethod
def from_png_file(path: str) -> Image:
def from_png_file(path: str | Path) -> Image:
"""
Create an image from a PNG file.
Parameters
----------
path : str
path : str | Path
The path to the PNG file.
Returns
Expand Down Expand Up @@ -86,25 +86,25 @@ def format(self) -> ImageFormat:
# Conversion
# ------------------------------------------------------------------------------------------------------------------

def to_jpeg_file(self, path: str) -> None:
def to_jpeg_file(self, path: str | Path) -> None:
"""
Save the image as a JPEG file.
Parameters
----------
path : str
path : str | Path
The path to the JPEG file.
"""
Path(path).parent.mkdir(parents=True, exist_ok=True)
self._image.save(path, format="jpeg")

def to_png_file(self, path: str) -> None:
def to_png_file(self, path: str | Path) -> None:
"""
Save the image as a PNG file.
Parameters
----------
path : str
path : str | Path
The path to the PNG file.
"""
Path(path).parent.mkdir(parents=True, exist_ok=True)
Expand Down
16 changes: 8 additions & 8 deletions src/safeds/data/tabular/containers/_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ class Table:
# ------------------------------------------------------------------------------------------------------------------

@staticmethod
def from_csv_file(path: str) -> Table:
def from_csv_file(path: str | Path) -> Table:
"""
Read data from a CSV file into a table.
Parameters
----------
path : str
path : str | Path
The path to the CSV file.
Returns
Expand All @@ -87,13 +87,13 @@ def from_csv_file(path: str) -> Table:
raise FileNotFoundError(f'File "{path}" does not exist') from exception

@staticmethod
def from_json_file(path: str) -> Table:
def from_json_file(path: str | Path) -> Table:
"""
Read data from a JSON file into a table.
Parameters
----------
path : str
path : str | Path
The path to the JSON file.
Returns
Expand Down Expand Up @@ -1200,7 +1200,7 @@ def plot_scatterplot(self, x_column_name: str, y_column_name: str) -> Image:
# Conversion
# ------------------------------------------------------------------------------------------------------------------

def to_csv_file(self, path: str) -> None:
def to_csv_file(self, path: str | Path) -> None:
"""
Write the data from the table into a CSV file.
Expand All @@ -1209,15 +1209,15 @@ def to_csv_file(self, path: str) -> None:
Parameters
----------
path : str
path : str | Path
The path to the output file.
"""
Path(path).parent.mkdir(parents=True, exist_ok=True)
data_to_csv = self._data.copy()
data_to_csv.columns = self._schema.column_names
data_to_csv.to_csv(path, index=False)

def to_json_file(self, path: str) -> None:
def to_json_file(self, path: str | Path) -> None:
"""
Write the data from the table into a JSON file.
Expand All @@ -1226,7 +1226,7 @@ def to_json_file(self, path: str) -> None:
Parameters
----------
path : str
path : str | Path
The path to the output file.
"""
Path(path).parent.mkdir(parents=True, exist_ok=True)
Expand Down
4 changes: 2 additions & 2 deletions tests/helpers/_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
_resources_root = Path(__file__).parent / ".." / "resources"


def resolve_resource_path(resource_path: str) -> str:
def resolve_resource_path(resource_path: str | Path) -> str:
"""
Resolve a path relative to the `resources` directory to an absolute path.
Parameters
----------
resource_path : str
resource_path : str | Path
The path to the resource relative to the `resources` directory.
Returns
Expand Down
52 changes: 42 additions & 10 deletions tests/safeds/data/image/containers/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,33 @@
class TestFromJpegFile:
@pytest.mark.parametrize(
"path",
["image/white_square.jpg"],
["image/white_square.jpg", Path("image/white_square.jpg")],
)
def test_should_load_jpeg_file(self, path: str) -> None:
def test_should_load_jpeg_file(self, path: str | Path) -> None:
Image.from_jpeg_file(resolve_resource_path(path))

@pytest.mark.parametrize(
"path",
["image/missing_file.jpg"],
["image/missing_file.jpg", Path("image/missing_file.jpg")],
)
def test_should_raise_if_file_not_found(self, path: str) -> None:
def test_should_raise_if_file_not_found(self, path: str | Path) -> None:
with pytest.raises(FileNotFoundError):
Image.from_jpeg_file(resolve_resource_path(path))


class TestFromPngFile:
@pytest.mark.parametrize(
"path",
["image/white_square.png"],
["image/white_square.png", Path("image/white_square.png")],
)
def test_should_load_png_file(self, path: str) -> None:
def test_should_load_png_file(self, path: str | Path) -> None:
Image.from_png_file(resolve_resource_path(path))

@pytest.mark.parametrize(
"path",
["image/missing_file.png"],
["image/missing_file.png", Path("image/missing_file.png")],
)
def test_should_raise_if_file_not_found(self, path: str) -> None:
def test_should_raise_if_file_not_found(self, path: str | Path) -> None:
with pytest.raises(FileNotFoundError):
Image.from_png_file(resolve_resource_path(path))

Expand All @@ -59,7 +59,7 @@ class TestToJpegFile:
"path",
["image/white_square.jpg"],
)
def test_should_save_jpeg_file(self, path: str) -> None:
def test_should_save_jpeg_file_by_str(self, path: str) -> None:
image = Image.from_jpeg_file(resolve_resource_path(path))

with NamedTemporaryFile() as tmp_file:
Expand All @@ -71,13 +71,29 @@ def test_should_save_jpeg_file(self, path: str) -> None:

assert image._image.tobytes() == image_read_back._image.tobytes()

@pytest.mark.parametrize(
"path",
["image/white_square.jpg"],
)
def test_should_save_jpeg_file_by_path(self, path: str) -> None:
image = Image.from_jpeg_file(resolve_resource_path(path))

with NamedTemporaryFile() as tmp_file:
tmp_file.close()
with Path(tmp_file.name).open("wb") as tmp_write_file:
image.to_jpeg_file(Path(tmp_write_file.name))
with Path(tmp_file.name).open("rb") as tmp_read_file:
image_read_back = Image.from_jpeg_file(tmp_read_file.name)

assert image._image.tobytes() == image_read_back._image.tobytes()


class TestToPngFile:
@pytest.mark.parametrize(
"path",
["image/white_square.png"],
)
def test_should_save_png_file(self, path: str) -> None:
def test_should_save_png_file_by_str(self, path: str) -> None:
image = Image.from_png_file(resolve_resource_path(path))

with NamedTemporaryFile() as tmp_file:
Expand All @@ -89,6 +105,22 @@ def test_should_save_png_file(self, path: str) -> None:

assert image._image.tobytes() == image_read_back._image.tobytes()

@pytest.mark.parametrize(
"path",
["image/white_square.png"],
)
def test_should_save_png_file_by_path(self, path: str) -> None:
image = Image.from_png_file(resolve_resource_path(path))

with NamedTemporaryFile() as tmp_file:
tmp_file.close()
with Path(tmp_file.name).open("wb") as tmp_write_file:
image.to_png_file(Path(tmp_write_file.name))
with Path(tmp_file.name).open("rb") as tmp_read_file:
image_read_back = Image.from_png_file(tmp_read_file.name)

assert image._image.tobytes() == image_read_back._image.tobytes()


class TestReprJpeg:
@pytest.mark.parametrize(
Expand Down
18 changes: 14 additions & 4 deletions tests/safeds/data/tabular/containers/_table/test_from_csv_file.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
from pathlib import Path

import pytest
from safeds.data.tabular.containers import Table

from tests.helpers import resolve_resource_path


def test_from_csv_file_valid() -> None:
table = Table.from_csv_file(resolve_resource_path("table.csv"))
@pytest.mark.parametrize(
"path",
["table.csv", Path("table.csv")],
)
def test_from_csv_file_valid(path: str | Path) -> None:
table = Table.from_csv_file(resolve_resource_path(path))
assert table.get_column("A").get_value(0) == 1
assert table.get_column("B").get_value(0) == 2


def test_from_csv_file_invalid() -> None:
@pytest.mark.parametrize(
"path",
["test_table_from_csv_file_invalid.csv", Path("test_table_from_csv_file_invalid.csv")],
)
def test_from_csv_file_invalid(path: str | Path) -> None:
with pytest.raises(FileNotFoundError):
Table.from_csv_file(resolve_resource_path("test_table_from_csv_file_invalid.csv"))
Table.from_csv_file(resolve_resource_path(path))
18 changes: 14 additions & 4 deletions tests/safeds/data/tabular/containers/_table/test_from_json_file.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
from pathlib import Path

import pytest
from safeds.data.tabular.containers import Table

from tests.helpers import resolve_resource_path


def test_from_json_file_valid() -> None:
table = Table.from_json_file(resolve_resource_path("table.json"))
@pytest.mark.parametrize(
"path",
["table.json", Path("table.json")],
)
def test_from_json_file_valid(path: str | Path) -> None:
table = Table.from_json_file(resolve_resource_path(path))
assert table.get_column("A").get_value(0) == 1
assert table.get_column("B").get_value(0) == 2


def test_from_json_file_invalid() -> None:
@pytest.mark.parametrize(
"path",
["test_table_from_json_file_invalid.json", Path("test_table_from_json_file_invalid.json")],
)
def test_from_json_file_invalid(path: str | Path) -> None:
with pytest.raises(FileNotFoundError):
Table.from_json_file(resolve_resource_path("test_table_from_json_file_invalid.json"))
Table.from_json_file(resolve_resource_path(path))
13 changes: 12 additions & 1 deletion tests/safeds/data/tabular/containers/_table/test_to_csv_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from safeds.data.tabular.containers import Table


def test_to_csv_file() -> None:
def test_to_csv_file_by_str() -> None:
table = Table.from_dict({"col1": ["col1_1"], "col2": ["col2_1"]})
with NamedTemporaryFile() as tmp_table_file:
tmp_table_file.close()
Expand All @@ -13,3 +13,14 @@ def test_to_csv_file() -> None:
with Path(tmp_table_file.name).open("r", encoding="utf-8") as tmp_file:
table_r = Table.from_csv_file(tmp_file.name)
assert table == table_r


def test_to_csv_file_by_path() -> None:
table = Table.from_dict({"col1": ["col1_1"], "col2": ["col2_1"]})
with NamedTemporaryFile() as tmp_table_file:
tmp_table_file.close()
with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file:
table.to_csv_file(Path(tmp_file.name))
with Path(tmp_table_file.name).open("r", encoding="utf-8") as tmp_file:
table_r = Table.from_csv_file(Path(tmp_file.name))
assert table == table_r
13 changes: 12 additions & 1 deletion tests/safeds/data/tabular/containers/_table/test_to_json_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from safeds.data.tabular.containers import Table


def test_to_json_file() -> None:
def test_to_json_file_by_str() -> None:
table = Table.from_dict({"col1": ["col1_1"], "col2": ["col2_1"]})
with NamedTemporaryFile() as tmp_table_file:
tmp_table_file.close()
Expand All @@ -13,3 +13,14 @@ def test_to_json_file() -> None:
with Path(tmp_table_file.name).open("r", encoding="utf-8") as tmp_file:
table_r = Table.from_json_file(tmp_file.name)
assert table == table_r


def test_to_json_file_by_path() -> None:
table = Table.from_dict({"col1": ["col1_1"], "col2": ["col2_1"]})
with NamedTemporaryFile() as tmp_table_file:
tmp_table_file.close()
with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file:
table.to_json_file(Path(tmp_file.name))
with Path(tmp_table_file.name).open("r", encoding="utf-8") as tmp_file:
table_r = Table.from_json_file(Path(tmp_file.name))
assert table == table_r

0 comments on commit 2b58c82

Please sign in to comment.