From ca0a76ce635ab47f318c1488eeeb1519ca8a44c7 Mon Sep 17 00:00:00 2001 From: Amine Lemaizi <40530011+aminelemaizi@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:44:52 +0100 Subject: [PATCH 1/2] adding cached textual outputs --- coded-flows/coded_flows/utils/media.py | 31 ++++++++++-- coded-flows/tests/test_data_save.py | 2 +- coded-flows/tests/test_text_save.py | 70 ++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 coded-flows/tests/test_text_save.py diff --git a/coded-flows/coded_flows/utils/media.py b/coded-flows/coded_flows/utils/media.py index 575895e..954830e 100644 --- a/coded-flows/coded_flows/utils/media.py +++ b/coded-flows/coded_flows/utils/media.py @@ -129,7 +129,7 @@ def save_data_to_json( elif isinstance(data, tuple): col_data = list(data) else: - raise TypeError(f"Unsupported data type: {type(data)}") + raise TypeError(f"Unsupported data type: {type(data).__name__}") normalized_data.append(pd.Series(col_data, name=label)) max_length = max(max_length, len(col_data)) @@ -160,7 +160,6 @@ def save_data_to_parquet( isinstance(data, list) and all(isinstance(item, dict) for item in data[:50]) ) ): - try: if isinstance(data, pd.DataFrame): data.to_parquet( @@ -194,6 +193,32 @@ def save_data_to_parquet( file_path, row_group_size=50000, index=False, engine="pyarrow" ) else: - raise TypeError(f"Unsupported data type: {type(data)}") + raise TypeError(f"Unsupported data type: {type(data).__name__}") return file_path + + +def save_text_to_temp( + data: Any, + filename=None, +) -> str: + random_filename = f"cfdata_{filename if filename else uuid.uuid4().hex}.txt" + temp_dir = os.path.join(tempfile.gettempdir(), "coded-flows-media") + os.makedirs(temp_dir, exist_ok=True) + file_path = os.path.join(temp_dir, random_filename) + + text_to_write = "" + if isinstance(data, str): + text_to_write = data + elif isinstance(data, (bytes, bytearray)): + try: + text_to_write = data.decode("utf-8") + except UnicodeDecodeError: + raise TypeError(f"Data is bytes but not decodable with 'utf-8' encoding.") + else: + raise TypeError(f"Expected str or bytes, got {type(data).__name__}") + + with open(file_path, "w", encoding="utf-8") as f: + f.write(text_to_write) + + return file_path diff --git a/coded-flows/tests/test_data_save.py b/coded-flows/tests/test_data_save.py index f26ebc3..f33e86d 100644 --- a/coded-flows/tests/test_data_save.py +++ b/coded-flows/tests/test_data_save.py @@ -65,7 +65,7 @@ def test_invalid_data_type(): invalid_data = {1, 2, 3} # Set, not supported labels = ["x"] - with pytest.raises(TypeError, match="Unsupported data type: "): + with pytest.raises(TypeError, match="Unsupported data type: set"): save_data_to_json(invalid_data, labels=labels) diff --git a/coded-flows/tests/test_text_save.py b/coded-flows/tests/test_text_save.py new file mode 100644 index 0000000..b3a19b2 --- /dev/null +++ b/coded-flows/tests/test_text_save.py @@ -0,0 +1,70 @@ +import os +import tempfile +import uuid +import pytest +from coded_flows.utils.media import save_text_to_temp + + +def test_save_text_to_temp_str(tmp_path, monkeypatch): + """Test saving a simple string input.""" + monkeypatch.setattr(tempfile, "gettempdir", lambda: str(tmp_path)) + text = "hello world" + path = save_text_to_temp(text, "testfile") + + # Ensure correct path + assert path.endswith("coded-flows-media/cfdata_testfile.txt") + assert os.path.exists(path) + + # Ensure correct content + with open(path, "r", encoding="utf-8") as f: + assert f.read() == text + + +def test_save_text_to_temp_bytes(monkeypatch, tmp_path): + """Test saving UTF-8 encodable bytes input.""" + monkeypatch.setattr(tempfile, "gettempdir", lambda: str(tmp_path)) + data = "hello bytes".encode("utf-8") + path = save_text_to_temp(data, "bytesfile") + + with open(path, "r", encoding="utf-8") as f: + assert f.read() == "hello bytes" + + +def test_save_text_to_temp_bytes_not_decodable(monkeypatch, tmp_path): + """Test saving non-UTF-8 bytes raises TypeError.""" + monkeypatch.setattr(tempfile, "gettempdir", lambda: str(tmp_path)) + data = b"\xff\xfe" # invalid UTF-8 + + with pytest.raises(TypeError, match="not decodable"): + save_text_to_temp(data, "badbytes") + + +def test_save_text_to_temp_invalid_type(monkeypatch, tmp_path): + """Test passing an unsupported type raises TypeError.""" + monkeypatch.setattr(tempfile, "gettempdir", lambda: str(tmp_path)) + + with pytest.raises(TypeError, match="Expected str or bytes"): + save_text_to_temp(1234, "invalid") + + +def test_save_text_to_temp_random_filename(monkeypatch, tmp_path): + """Test that UUID-based filenames are generated when filename is None.""" + monkeypatch.setattr(tempfile, "gettempdir", lambda: str(tmp_path)) + + fake_uuid = uuid.UUID("12345678123456781234567812345678") + monkeypatch.setattr(uuid, "uuid4", lambda: fake_uuid) + + path = save_text_to_temp("random", None) + assert path.endswith( + "coded-flows-media/cfdata_12345678123456781234567812345678.txt" + ) + assert os.path.exists(path) + + +def test_directory_creation(monkeypatch, tmp_path): + """Ensure directory is created if not existing.""" + target_dir = tmp_path / "nested-temp" + monkeypatch.setattr(tempfile, "gettempdir", lambda: str(target_dir)) + + path = save_text_to_temp("make dir", "dirtest") + assert os.path.exists(os.path.dirname(path)) From 37194cdcd39128ce57c46f1b565fca2037d124da Mon Sep 17 00:00:00 2001 From: Amine Lemaizi <40530011+aminelemaizi@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:46:23 +0100 Subject: [PATCH 2/2] specifying the version --- coded-flows/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coded-flows/pyproject.toml b/coded-flows/pyproject.toml index 65f1db3..d5a72b7 100644 --- a/coded-flows/pyproject.toml +++ b/coded-flows/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "coded-flows" -version = "0.6.2" +version = "0.6.3" description = "Various utilities for Coded Flows" authors = ["COLOR CODED CODES "] readme = "README.md"