Skip to content

Conversation

@saadiqbal09
Copy link

@saadiqbal09 saadiqbal09 commented Dec 26, 2025

This PR adds utility functions to export PSLab sensor data
to CSV and JSON formats.

  • Useful for IoT data logging and analysis
  • Pure Python implementation
  • Includes basic pytest-based tests
  • No hardware required

This improves data usability for PSLab users.

Summary by Sourcery

Add utilities for exporting PSLab sensor data to common file formats and ensure they are covered by basic tests.

New Features:

  • Introduce helpers to export PSLab sensor data to CSV and JSON files.

Tests:

  • Add pytest-based tests verifying CSV and JSON export create output files and that exporting empty data raises an error.

@sourcery-ai
Copy link

sourcery-ai bot commented Dec 26, 2025

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds pytest-based tests around new CSV and JSON data export utilities for PSLab sensor data, including file creation checks and validation for empty input data.

File-Level Changes

Change Details Files
Introduce basic tests for CSV and JSON export utilities to verify file creation and input validation.
  • Add tests that call CSV and JSON export helpers with simple dict-list data and assert the output files are created in a temporary directory
  • Add a negative test that ensures exporting empty data to CSV raises a ValueError, defining expected behavior for invalid input
tests/test_data_export.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@saadiqbal09
Copy link
Author

This is my first contribution to PSLab.
Happy to update the implementation based on feedback.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • Consider defining and enforcing a consistent behavior for empty input across both export_to_csv and export_to_json (e.g., both raising ValueError or both producing empty files), so callers don’t have to handle each exporter differently.
  • It may be useful for export_to_csv and export_to_json to accept file-like objects in addition to file paths, which would make them easier to integrate with in-memory streams and higher-level APIs.
  • Clarify and standardize how the exporters handle records with heterogeneous or missing keys (e.g., column ordering, default values), and ensure the implementation consistently applies that strategy.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider defining and enforcing a consistent behavior for empty input across both `export_to_csv` and `export_to_json` (e.g., both raising `ValueError` or both producing empty files), so callers don’t have to handle each exporter differently.
- It may be useful for `export_to_csv` and `export_to_json` to accept file-like objects in addition to file paths, which would make them easier to integrate with in-memory streams and higher-level APIs.
- Clarify and standardize how the exporters handle records with heterogeneous or missing keys (e.g., column ordering, default values), and ensure the implementation consistently applies that strategy.

## Individual Comments

### Comment 1
<location> `tests/test_data_export.py:4-8` </location>
<code_context>
+import pytest
+from pslab.utils.data_export import export_to_csv, export_to_json
+
+def test_export_csv_creates_file(tmp_path):
+    data = [{"a": 1, "b": 2}]
+    file_path = tmp_path / "data.csv"
+    export_to_csv(data, str(file_path))
+    assert file_path.exists()
+
+def test_export_json_creates_file(tmp_path):
</code_context>

<issue_to_address>
**suggestion (testing):** CSV export test only checks that the file exists but not that its contents are correct.

This test would still pass if the CSV had wrong headers, delimiters, or malformed rows. Please extend it to read and assert the contents—for example, that the header matches the expected columns, the row count is correct, and at least one data row matches the input—so it verifies the export logic, not just file creation.

Suggested implementation:

```python
import csv
import pytest
from pslab.utils.data_export import export_to_csv, export_to_json

def test_export_csv_creates_file(tmp_path):
    data = [{"a": 1, "b": 2}]
    file_path = tmp_path / "data.csv"

    export_to_csv(data, str(file_path))

    # File is created
    assert file_path.exists()

    # Contents are correct
    with file_path.open(newline="") as f:
        reader = csv.DictReader(f)
        # Header matches expected columns
        assert reader.fieldnames == ["a", "b"]

        rows = list(reader)
        # Row count is correct
        assert len(rows) == 1

        row = rows[0]
        # Row data matches input (compare as strings to be robust)
        assert row["a"] == str(data[0]["a"])
        assert row["b"] == str(data[0]["b"])

```

```python
def test_export_json_creates_file(tmp_path):
    data = [{"x": 10}]
    file_path = tmp_path / "data.json"
    export_to_json(data, str(file_path))
    assert file_path.exists()

```
</issue_to_address>

### Comment 2
<location> `tests/test_data_export.py:10-8` </location>
<code_context>
+    export_to_csv(data, str(file_path))
+    assert file_path.exists()
+
+def test_export_json_creates_file(tmp_path):
+    data = [{"x": 10}]
+    file_path = tmp_path / "data.json"
+    export_to_json(data, str(file_path))
+    assert file_path.exists()
+
+def test_export_empty_data_raises_error():
</code_context>

<issue_to_address>
**suggestion (testing):** JSON export test should validate the serialized content, not just file creation.

Consider mirroring the CSV test by loading the JSON (e.g., with `json.load`) and asserting the parsed structure and values match `data`. This will catch issues with encoding, formatting, or changes to the top-level container type.

Suggested implementation:

```python
import json
import pytest
from pslab.utils.data_export import export_to_csv, export_to_json

```

```python
def test_export_json_creates_file(tmp_path):
    data = [{"x": 10}]
    file_path = tmp_path / "data.json"

    export_to_json(data, str(file_path))

    assert file_path.exists()

    with file_path.open("r", encoding="utf-8") as f:
        loaded = json.load(f)

    assert loaded == data

```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 4 to 8
def test_export_csv_creates_file(tmp_path):
data = [{"a": 1, "b": 2}]
file_path = tmp_path / "data.csv"
export_to_csv(data, str(file_path))
assert file_path.exists()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): CSV export test only checks that the file exists but not that its contents are correct.

This test would still pass if the CSV had wrong headers, delimiters, or malformed rows. Please extend it to read and assert the contents—for example, that the header matches the expected columns, the row count is correct, and at least one data row matches the input—so it verifies the export logic, not just file creation.

Suggested implementation:

import csv
import pytest
from pslab.utils.data_export import export_to_csv, export_to_json

def test_export_csv_creates_file(tmp_path):
    data = [{"a": 1, "b": 2}]
    file_path = tmp_path / "data.csv"

    export_to_csv(data, str(file_path))

    # File is created
    assert file_path.exists()

    # Contents are correct
    with file_path.open(newline="") as f:
        reader = csv.DictReader(f)
        # Header matches expected columns
        assert reader.fieldnames == ["a", "b"]

        rows = list(reader)
        # Row count is correct
        assert len(rows) == 1

        row = rows[0]
        # Row data matches input (compare as strings to be robust)
        assert row["a"] == str(data[0]["a"])
        assert row["b"] == str(data[0]["b"])
def test_export_json_creates_file(tmp_path):
    data = [{"x": 10}]
    file_path = tmp_path / "data.json"
    export_to_json(data, str(file_path))
    assert file_path.exists()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant