Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions datamimic_ce/tasks/task_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,20 @@ def gen_task_load_data_from_source_or_script(
else:
# Evaluate script in source
source_data = context.evaluate_python_expression(stmt.script)
elif source_str.endswith(".wgt.csv"):
# A ".wgt.csv" file is headerless (value|weight, no column names) - the plain CSV
# reader below would treat its first data row as a header, producing nonsense column
# names and one fewer row than the file has. Unlike ".wgt.ent.csv" (a normal headered
# CSV that merely has an extra "weight" column - reading it plainly is coherent, just
# unweighted), there is no coherent plain-CSV reading of this format at all. <key
# source="...wgt.csv"> already applies its weights correctly; <generate>-level
# weighted-entity sourcing is real work, not yet done - fail loudly instead of
# silently generating garbage.
raise ValueError(
f"<generate> '{stmt.full_name}': source '{source_str}' is a headerless weighted "
f"value|weight file - not supported at <generate>-level (only <key source=...> "
f"applies '.wgt.csv' weights today)"
)
# Load data from CSV
elif source_str.endswith(".csv"):
source_data = DataSourceRegistry.load_csv_file(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
true|80
false|20
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
id,name,weight
1,Cheap,80
2,Expensive,20
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<setup>
<generate name="rows" source="data/products.wgt.ent.csv" separator="," count="5" target="JSON"/>
</setup>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<setup>
<generate name="rows" source="data/active.wgt.csv" count="5" target="JSON"/>
</setup>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# DATAMIMIC
# Copyright (c) 2023-2025 Rapiddweller Asia Co., Ltd.
# This software is licensed under the MIT License.
# See LICENSE file for the full text of the license.
# For questions and support, contact: info@rapiddweller.com

"""<generate source="x.wgt.csv"> (the headerless value|weight format) falls through to the plain
CSV reader, which has no coherent way to read it - it would treat the first data row as a header,
producing nonsense column names and one fewer row than the file has. Full weighted-entity support
at <generate>-level needs pagination-core work (see PR #194 discussion); until that lands, fail
loudly instead of silently producing garbage.

".wgt.ent.csv" is different: it's a normal headered CSV that happens to carry an extra "weight"
column, so reading it plainly (ignoring the weight, no resampling) is coherent - just unweighted.
An existing test (test_source_script/test_iterate_source_scripted.xml) already relies on exactly
that, so this must keep working."""

from pathlib import Path

import pytest

from datamimic_ce.data_mimic_test import DataMimicTest

_dir = Path(__file__).resolve().parent


def test_generate_source_wgt_csv_raises():
engine = DataMimicTest(_dir, "generate_wgt_plain.xml", capture_test_result=True)
with pytest.raises(ValueError, match=r"\.wgt\.csv"):
engine.test_with_timer()


def test_generate_source_wgt_ent_csv_reads_as_plain_csv():
"""Not weighted (no resampling, no bias toward the higher-weight row) - just an ordinary
headered CSV read, weight column included as literal data. Must NOT raise."""
engine = DataMimicTest(_dir, "generate_wgt_ent.xml", capture_test_result=True)
engine.test_with_timer()
rows = engine.capture_result()["rows"]
assert {row["name"] for row in rows} <= {"Cheap", "Expensive"}
assert all("weight" in row for row in rows)