Skip to content

Commit a417abc

Browse files
authored
Merge branch 'develop' into debug/oom
2 parents ad6ceb7 + 87c63fe commit a417abc

File tree

10 files changed

+118
-12
lines changed

10 files changed

+118
-12
lines changed

.github/workflows/build-package.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2424

2525
- name: 🐍 Install uv and set Python version ${{ inputs.python-version }}
26-
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
26+
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
2727
with:
2828
python-version: ${{ inputs.python-version }}
2929
activate-environment: true
@@ -50,7 +50,7 @@ jobs:
5050
twine check --strict dist/*
5151
5252
- name: 📤 Upload distribution artifacts
53-
uses: actions/upload-artifact@v6
53+
uses: actions/upload-artifact@v7
5454
with:
5555
name: dist
5656
path: dist/

.github/workflows/ci-build-docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2626

2727
- name: 🐍 Install uv and set Python
28-
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
28+
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
2929
with:
3030
python-version: "3.10"
3131
activate-environment: true

.github/workflows/ci-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
3737

3838
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
39-
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
39+
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
4040
with:
4141
python-version: ${{ matrix.python-version }}
4242
activate-environment: true

.github/workflows/publish-docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
fetch-depth: 0
3232

3333
- name: 🐍 Install uv and set Python
34-
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
34+
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
3535
with:
3636
python-version: "3.10"
3737
activate-environment: true

.github/workflows/publish-pre-release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
contents: read # Required for checkout
3535
steps:
3636
- name: 📥 Download distribution artifacts
37-
uses: actions/download-artifact@v7
37+
uses: actions/download-artifact@v8
3838
with:
3939
name: dist
4040
path: dist/

.github/workflows/publish-release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
contents: write # Required for checkout and upload assets
3232
steps:
3333
- name: 📥 Download distribution artifacts
34-
uses: actions/download-artifact@v7
34+
uses: actions/download-artifact@v8
3535
with:
3636
name: dist
3737
path: dist/

.github/workflows/publish-testpypi.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
contents: read # Required for checkout
3030
steps:
3131
- name: 📥 Download distribution artifacts
32-
uses: actions/download-artifact@v7
32+
uses: actions/download-artifact@v8
3333
with:
3434
name: dist
3535
path: dist/

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ repos:
3434
args: ["--print-width=120"]
3535

3636
- repo: https://github.com/tox-dev/pyproject-fmt
37-
rev: v2.16.0
37+
rev: v2.16.2
3838
hooks:
3939
- id: pyproject-fmt
4040

@@ -44,7 +44,7 @@ repos:
4444
- id: validate-pyproject
4545

4646
- repo: https://github.com/astral-sh/ruff-pre-commit
47-
rev: v0.15.1
47+
rev: v0.15.2
4848
hooks:
4949
- id: ruff-check
5050
args: [--fix]

src/supervision/dataset/core.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import numpy.typing as npt
1313

1414
from supervision.classification.core import Classifications
15+
from supervision.config import CLASS_NAME_DATA_FIELD
1516
from supervision.dataset.formats.coco import (
1617
load_coco_annotations,
1718
save_coco_annotations,
@@ -84,6 +85,14 @@ def __init__(
8485
)
8586
self.annotations = annotations
8687

88+
if self.classes:
89+
np_classes = np.array(self.classes)
90+
for annotation in self.annotations.values():
91+
if annotation.class_id is not None:
92+
annotation.data[CLASS_NAME_DATA_FIELD] = np_classes[
93+
annotation.class_id
94+
]
95+
8796
# Eliminate duplicates while preserving order
8897
self.image_paths = list(dict.fromkeys(images))
8998

tests/dataset/test_core.py

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
from __future__ import annotations
22

33
from contextlib import ExitStack as DoesNotRaise
4+
from pathlib import Path
45

6+
import numpy as np
57
import pytest
68

7-
from supervision import DetectionDataset
8-
from tests.helpers import _create_detections
9+
from supervision import DetectionDataset, Detections
10+
from supervision.config import CLASS_NAME_DATA_FIELD
11+
from tests.helpers import _create_detections, create_yolo_dataset
912

1013

1114
@pytest.mark.parametrize(
@@ -187,3 +190,97 @@ def test_dataset_merge(
187190
with exception:
188191
result = DetectionDataset.merge(dataset_list=dataset_list)
189192
assert result == expected_result
193+
194+
195+
class TestClassNamePopulation:
196+
"""Verify that DetectionDataset populates CLASS_NAME_DATA_FIELD on init."""
197+
198+
def test_class_name_populated_on_init(self) -> None:
199+
"""Basic case: class_name data field is set from classes and class_id."""
200+
dataset = DetectionDataset(
201+
classes=["dog", "cat"],
202+
images=["img1.png"],
203+
annotations={
204+
"img1.png": _create_detections(
205+
xyxy=[[0, 0, 10, 10], [20, 20, 30, 30]],
206+
class_id=[0, 1],
207+
),
208+
},
209+
)
210+
annotation = dataset.annotations["img1.png"]
211+
assert CLASS_NAME_DATA_FIELD in annotation.data
212+
np.testing.assert_array_equal(
213+
annotation.data[CLASS_NAME_DATA_FIELD],
214+
np.array(["dog", "cat"]),
215+
)
216+
217+
def test_class_name_with_empty_annotations(self) -> None:
218+
"""Empty Detections should not raise an error."""
219+
dataset = DetectionDataset(
220+
classes=["dog"],
221+
images=["img1.png"],
222+
annotations={"img1.png": Detections.empty()},
223+
)
224+
annotation = dataset.annotations["img1.png"]
225+
assert CLASS_NAME_DATA_FIELD in annotation.data
226+
assert len(annotation.data[CLASS_NAME_DATA_FIELD]) == 0
227+
228+
def test_class_name_with_empty_classes(self) -> None:
229+
"""When classes is empty, class_name should not be populated."""
230+
dataset = DetectionDataset(
231+
classes=[],
232+
images=[],
233+
annotations={},
234+
)
235+
assert len(dataset.annotations) == 0
236+
237+
def test_class_name_after_merge(self) -> None:
238+
"""After merging datasets, class_name must match remapped class_id."""
239+
ds1 = DetectionDataset(
240+
classes=["dog", "person"],
241+
images=["img1.png"],
242+
annotations={
243+
"img1.png": _create_detections(xyxy=[[0, 0, 10, 10]], class_id=[0]),
244+
},
245+
)
246+
ds2 = DetectionDataset(
247+
classes=["cat"],
248+
images=["img2.png"],
249+
annotations={
250+
"img2.png": _create_detections(xyxy=[[0, 0, 10, 10]], class_id=[0]),
251+
},
252+
)
253+
merged = DetectionDataset.merge([ds1, ds2])
254+
255+
# merged.classes is ["cat", "dog", "person"]
256+
# ds1's dog (0) -> dog (1), ds2's cat (0) -> cat (0)
257+
ann1 = merged.annotations["img1.png"]
258+
assert CLASS_NAME_DATA_FIELD in ann1.data
259+
np.testing.assert_array_equal(
260+
ann1.data[CLASS_NAME_DATA_FIELD], np.array(["dog"])
261+
)
262+
263+
ann2 = merged.annotations["img2.png"]
264+
assert CLASS_NAME_DATA_FIELD in ann2.data
265+
np.testing.assert_array_equal(
266+
ann2.data[CLASS_NAME_DATA_FIELD], np.array(["cat"])
267+
)
268+
269+
def test_class_name_from_yolo(self, tmp_path: Path) -> None:
270+
"""Integration test: from_yolo should produce class_name data."""
271+
dataset_info = create_yolo_dataset(
272+
str(tmp_path), num_images=2, classes=["cat", "dog"]
273+
)
274+
dataset = DetectionDataset.from_yolo(
275+
images_directory_path=dataset_info["images_dir"],
276+
annotations_directory_path=dataset_info["labels_dir"],
277+
data_yaml_path=dataset_info["data_yaml_path"],
278+
)
279+
280+
for _, annotation in dataset.annotations.items():
281+
if annotation.class_id is not None and len(annotation.class_id) > 0:
282+
assert CLASS_NAME_DATA_FIELD in annotation.data
283+
expected_names = np.array(dataset.classes)[annotation.class_id]
284+
np.testing.assert_array_equal(
285+
annotation.data[CLASS_NAME_DATA_FIELD], expected_names
286+
)

0 commit comments

Comments
 (0)