Skip to content

Commit 930cff3

Browse files
committed
remove it
1 parent 0358874 commit 930cff3

File tree

2 files changed

+230
-0
lines changed

2 files changed

+230
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
"""
2+
Test user_metadata export in roboflow-python SDK.
3+
4+
Related Linear Issues:
5+
- DATAMAN-98: roboflow-python should export user_metadata on code
6+
- DATAMAN-99: roboflow-python version export with user_metadata
7+
8+
This test validates that user_metadata is properly exported when downloading
9+
dataset versions via the SDK.
10+
11+
Uses staging project: model-evaluation-workspace/donut-2-lcfx0/28
12+
This project has tags and metadata on its images.
13+
14+
FINDINGS (2026-01-30):
15+
=====================
16+
1. COCO format export: ✅ WORKS
17+
- user_metadata is included in image.extra.user_metadata
18+
- Example: {"id": 0, ..., "extra": {"name": "...", "user_metadata": {"yummy": 0}}}
19+
20+
2. YOLOv8 format export:
21+
- Standard YOLO format (images + txt labels)
22+
- No dedicated metadata file (expected - YOLO format doesn't have metadata concept)
23+
24+
3. SDK Changes Needed: NONE
25+
- version.download() downloads ZIP from server
26+
- Server (roboflow-zip) already includes user_metadata in COCO JSON
27+
- SDK extracts ZIP locally
28+
- user_metadata is available in the downloaded files
29+
"""
30+
import os
31+
import sys
32+
import json
33+
import glob
34+
35+
thisdir = os.path.dirname(os.path.abspath(__file__))
36+
os.environ["ROBOFLOW_CONFIG_DIR"] = f"{thisdir}/data/.config"
37+
# Use staging API
38+
os.environ["API_URL"] = "https://api.roboflow.one"
39+
40+
rootdir = os.path.abspath(f"{thisdir}/../..")
41+
sys.path.append(rootdir)
42+
43+
from roboflow import Roboflow
44+
45+
46+
def _get_manual_api_key():
47+
api_key = os.getenv("ROBOFLOW_STAGING_API_KEY") or os.getenv("ROBOFLOW_API_KEY")
48+
if not api_key:
49+
raise RuntimeError("Set ROBOFLOW_STAGING_API_KEY (or ROBOFLOW_API_KEY) to run this manual test")
50+
return api_key
51+
52+
53+
def test_version_export_metadata():
54+
"""
55+
Test that user_metadata is exported with version download.
56+
"""
57+
rf = Roboflow(api_key=_get_manual_api_key())
58+
59+
# Access the staging project with metadata
60+
project = rf.workspace("model-evaluation-workspace").project("donut-2-lcfx0")
61+
version = project.version(28)
62+
63+
# Download in COCO format (metadata is in the JSON)
64+
print("Downloading version in COCO format...")
65+
dataset = version.download("coco", location=f"{thisdir}/metadata_test_coco", overwrite=True)
66+
print(f"\nDataset downloaded to: {dataset.location}")
67+
68+
# Look for annotation files
69+
json_files = glob.glob(f"{dataset.location}/**/*.json", recursive=True)
70+
print(f"\nFound JSON files: {json_files}")
71+
72+
# Check each JSON file for user_metadata in the extra field
73+
has_metadata = False
74+
for json_file in json_files:
75+
print(f"\n--- Inspecting: {json_file} ---")
76+
with open(json_file, 'r') as f:
77+
data = json.load(f)
78+
79+
# COCO format has 'images' array
80+
if 'images' in data:
81+
print(f"Found {len(data['images'])} images in COCO format")
82+
for i, img in enumerate(data['images'][:3]): # Check first 3
83+
print(f"\nImage {i}: {img.get('file_name', 'unknown')}")
84+
extra = img.get('extra', {})
85+
user_metadata = extra.get('user_metadata')
86+
if user_metadata:
87+
print(f" ✅ user_metadata (in extra): {user_metadata}")
88+
has_metadata = True
89+
else:
90+
print(f" ❌ No user_metadata in extra field")
91+
print(f" Keys in image: {list(img.keys())}")
92+
print(f" Keys in extra: {list(extra.keys()) if extra else 'N/A'}")
93+
else:
94+
print(f"Keys in JSON: {list(data.keys())[:10]}")
95+
96+
print("\n" + "=" * 60)
97+
if has_metadata:
98+
print("✅ TEST PASSED: user_metadata is exported in COCO format")
99+
print(" Location: image['extra']['user_metadata']")
100+
else:
101+
print("❌ TEST FAILED: user_metadata not found in exported files")
102+
print("=" * 60)
103+
104+
105+
if __name__ == "__main__":
106+
test_version_export_metadata()
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
"""
2+
Test user_metadata retrieval via SDK APIs.
3+
4+
Related Linear Issues:
5+
- DATAMAN-98: roboflow-python should export user_metadata on code
6+
- DATAMAN-99: roboflow-python version export with user_metadata
7+
8+
This test validates that user_metadata can be retrieved via the SDK's
9+
search() and image() methods.
10+
11+
Uses staging project: model-evaluation-workspace/donut-2-lcfx0
12+
This project has tags and metadata on its images.
13+
14+
API SUPPORT:
15+
============
16+
1. project.search() - Available fields:
17+
- id, name, created, annotations, labels, split, tags, owner, embedding, user_metadata
18+
- Default: ['id', 'name', 'created', 'labels']
19+
- To get tags: fields=['id', 'name', 'tags']
20+
- To get user_metadata: fields=['id', 'name', 'user_metadata']
21+
22+
2. project.image(id) - Image API:
23+
- Returns metadata in the 'metadata' field
24+
- Example: {'material': 'aluminium', 'yummy': 3, 'penguin': 2}
25+
"""
26+
import os
27+
import sys
28+
import json
29+
30+
thisdir = os.path.dirname(os.path.abspath(__file__))
31+
os.environ["ROBOFLOW_CONFIG_DIR"] = f"{thisdir}/data/.config"
32+
# Use staging API
33+
os.environ["API_URL"] = "https://api.roboflow.one"
34+
35+
rootdir = os.path.abspath(f"{thisdir}/../..")
36+
sys.path.append(rootdir)
37+
38+
from roboflow import Roboflow
39+
40+
41+
def _get_manual_api_key():
42+
api_key = os.getenv("ROBOFLOW_STAGING_API_KEY") or os.getenv("ROBOFLOW_API_KEY")
43+
if not api_key:
44+
raise RuntimeError("Set ROBOFLOW_STAGING_API_KEY (or ROBOFLOW_API_KEY) to run this manual test")
45+
return api_key
46+
47+
48+
def test_search_and_image_api():
49+
"""
50+
Test that user_metadata can be retrieved via project.search() and project.image().
51+
"""
52+
rf = Roboflow(api_key=_get_manual_api_key())
53+
54+
# Access the staging project with metadata
55+
project = rf.workspace("model-evaluation-workspace").project("donut-2-lcfx0")
56+
57+
print("=" * 60)
58+
print("TEST 1: project.search() - Default fields")
59+
print("=" * 60)
60+
results = project.search(limit=3)
61+
print(f"\nFound {len(results)} images")
62+
for i, img in enumerate(results):
63+
print(f"\nImage {i}: {img.get('name', 'unknown')}")
64+
print(f" Keys: {list(img.keys())}")
65+
66+
print("\n" + "=" * 60)
67+
print("TEST 2: project.search() - With tags field")
68+
print("=" * 60)
69+
results_tags = project.search(limit=3, fields=["id", "name", "tags"])
70+
print(f"\nFound {len(results_tags)} images")
71+
for i, img in enumerate(results_tags):
72+
print(f"\nImage {i}: {img.get('name', 'unknown')}")
73+
print(f" Keys: {list(img.keys())}")
74+
if 'tags' in img:
75+
print(f" ✅ tags: {img['tags']}")
76+
77+
print("\n" + "=" * 60)
78+
print("TEST 3: project.search() - With user_metadata field")
79+
print("=" * 60)
80+
try:
81+
results_metadata = project.search(limit=3, fields=["id", "name", "user_metadata"])
82+
print(f"\nFound {len(results_metadata)} images")
83+
for i, img in enumerate(results_metadata):
84+
print(f"\nImage {i}: {img.get('name', 'unknown')}")
85+
print(f" Keys: {list(img.keys())}")
86+
if 'user_metadata' in img:
87+
print(f" ✅ user_metadata: {img['user_metadata']}")
88+
else:
89+
print(f" ❌ No user_metadata in response")
90+
except Exception as e:
91+
print(f" ⚠️ Error: {e}")
92+
print(" (user_metadata field may not be deployed yet)")
93+
94+
print("\n" + "=" * 60)
95+
print("TEST 4: project.image(id) - Image API")
96+
print("=" * 60)
97+
98+
# Get images and check their metadata via image API
99+
images_with_metadata = 0
100+
for img in results[:5]:
101+
image_id = img.get('id')
102+
image_name = img.get('name', 'unknown')
103+
104+
print(f"\nFetching details for: {image_name}")
105+
details = project.image(image_id)
106+
107+
metadata = details.get('metadata', {})
108+
if metadata:
109+
print(f" ✅ metadata: {metadata}")
110+
images_with_metadata += 1
111+
else:
112+
print(f" ❌ No metadata (empty dict)")
113+
114+
print("\n" + "=" * 60)
115+
if images_with_metadata > 0:
116+
print(f"✅ TEST PASSED: {images_with_metadata}/{min(5, len(results))} images have metadata")
117+
print(" Access via: project.image(id)['metadata']")
118+
else:
119+
print("❌ TEST FAILED: No images have metadata")
120+
print("=" * 60)
121+
122+
123+
if __name__ == "__main__":
124+
test_search_and_image_api()

0 commit comments

Comments
 (0)