Skip to content

Commit cf87ebf

Browse files
authored
Merge pull request #408 from fgcz/deploy-20251215-02
Release
2 parents c8eecd6 + e75cdd0 commit cf87ebf

4 files changed

Lines changed: 26 additions & 14 deletions

File tree

bfabric/docs/changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ Minor breaking changes are still possible in `1.X.Y` but we try to announce them
99

1010
## \[Unreleased\]
1111

12+
## \[1.16.1\] - 2025-12-15
13+
14+
### Fixed
15+
16+
- `Dataset` correctly handles `None` values in items.
17+
1218
## \[1.16.0\] - 2025-12-15
1319

1420
### Added

bfabric/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
66
name = "bfabric"
77
description = "Python client for the B-Fabric API"
88
readme = "../README.md"
9-
version = "1.16.0"
9+
version = "1.16.1"
1010
license = { text = "GPL-3.0" }
1111
authors = [
1212
{ name = "Christian Panse", email = "cp@fgcz.ethz.ch" },

bfabric/src/bfabric/entities/dataset.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
from __future__ import annotations
22

33
import io
4-
from typing import TYPE_CHECKING
4+
from typing import TYPE_CHECKING, Annotated, Any
55

66
from polars import DataFrame
7-
from pydantic import BaseModel
7+
from pydantic import BaseModel, BeforeValidator
88

99
from bfabric.entities.core.entity import Entity
1010

@@ -18,8 +18,14 @@ class _AttributeData(BaseModel):
1818
type: str
1919

2020

21+
def _remove_none(value: Any) -> str: # pyright: ignore[reportAny, reportExplicitAny]
22+
if value is None:
23+
return ""
24+
return str(value) # pyright: ignore[reportAny]
25+
26+
2127
class _ItemDataField(BaseModel):
22-
value: str = ""
28+
value: Annotated[str, BeforeValidator(_remove_none)] = ""
2329
attributeposition: int
2430

2531

tests/bfabric/entities/test_dataset.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212

1313
@pytest.fixture()
14-
def mock_data_dict() -> dict[str, int | list[dict[str, str]] | list[dict[str, list[dict[str, str]]]]]:
14+
def mock_data_dict() -> dict[str, int | list[dict[str, str]] | list[dict[str, list[dict[str, str | None]]]]]:
1515
return {
1616
"id": 1234,
1717
"attribute": [
@@ -21,7 +21,7 @@ def mock_data_dict() -> dict[str, int | list[dict[str, str]] | list[dict[str, li
2121
"item": [
2222
{"field": [{"value": "Red", "attributeposition": "1"}, {"value": "Square", "attributeposition": "2"}]},
2323
{"field": [{"value": "Blue", "attributeposition": "1"}, {"value": "Circle", "attributeposition": "2"}]},
24-
{"field": [{"value": "Green", "attributeposition": "1"}, {"attributeposition": "2"}]},
24+
{"field": [{"value": None, "attributeposition": "1"}, {"attributeposition": "2"}]},
2525
],
2626
}
2727

@@ -37,7 +37,7 @@ def mock_data_dict_rearranged() -> dict[str, int | list[dict[str, str]] | list[d
3737
"item": [
3838
{"field": [{"value": "Square", "attributeposition": "2"}, {"value": "Red", "attributeposition": "1"}]},
3939
{"field": [{"value": "Circle", "attributeposition": "2"}, {"value": "Blue", "attributeposition": "1"}]},
40-
{"field": [{"attributeposition": "2"}, {"value": "Green", "attributeposition": "1"}]},
40+
{"field": [{"attributeposition": "2"}, {"value": "", "attributeposition": "1"}]},
4141
],
4242
}
4343

@@ -48,8 +48,8 @@ def mock_dataset(mock_data_dict: dict[str, Any], mock_client, bfabric_instance)
4848

4949

5050
@pytest.fixture()
51-
def mock_empty_dataset(mock_client) -> Dataset:
52-
return Dataset({"id": 1234, "attribute": [], "item": []}, client=mock_client)
51+
def mock_empty_dataset(mock_client, bfabric_instance) -> Dataset:
52+
return Dataset({"id": 1234, "attribute": [], "item": []}, client=mock_client, bfabric_instance=bfabric_instance)
5353

5454

5555
def test_data_dict(mock_dataset: Dataset, mock_data_dict: dict[str, Any]) -> None:
@@ -66,15 +66,15 @@ def test_column_types(mock_dataset: Dataset) -> None:
6666

6767

6868
@pytest.mark.parametrize("rearranged_data_dict", [True, False])
69-
def test_to_polars(request, rearranged_data_dict: bool, mock_client) -> None:
69+
def test_to_polars(request, rearranged_data_dict: bool, mock_client, bfabric_instance) -> None:
7070
data_dict = request.getfixturevalue("mock_data_dict_rearranged" if rearranged_data_dict else "mock_data_dict")
71-
mock_dataset = Dataset(data_dict, client=mock_client)
71+
mock_dataset = Dataset(data_dict, client=mock_client, bfabric_instance=bfabric_instance)
7272
df = mock_dataset.to_polars()
7373
pl.testing.assert_frame_equal(
7474
df,
7575
pl.DataFrame(
7676
{
77-
"Color": ["Red", "Blue", "Green"],
77+
"Color": ["Red", "Blue", ""],
7878
"Shape": ["Square", "Circle", ""],
7979
}
8080
),
@@ -93,7 +93,7 @@ def test_write_csv(mocker: MockFixture, mock_dataset: Dataset) -> None:
9393

9494
def test_get_csv(mock_dataset: Dataset) -> None:
9595
csv = mock_dataset.get_csv()
96-
assert csv == 'Color,Shape\nRed,Square\nBlue,Circle\nGreen,""\n'
96+
assert csv == 'Color,Shape\nRed,Square\nBlue,Circle\n"",""\n'
9797

9898

9999
def test_get_parquet(mock_dataset: Dataset) -> None:
@@ -103,7 +103,7 @@ def test_get_parquet(mock_dataset: Dataset) -> None:
103103
df,
104104
pl.DataFrame(
105105
{
106-
"Color": ["Red", "Blue", "Green"],
106+
"Color": ["Red", "Blue", ""],
107107
"Shape": ["Square", "Circle", ""],
108108
}
109109
),

0 commit comments

Comments
 (0)