|
| 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