Skip to content

feat(sdk): public wrappers for updating image metadata (DATAMAN-337) - #511

Merged
digaobarbosa merged 3 commits into
mainfrom
digao/sdk-image-metadata-wrappers
Jul 22, 2026
Merged

feat(sdk): public wrappers for updating image metadata (DATAMAN-337)#511
digaobarbosa merged 3 commits into
mainfrom
digao/sdk-image-metadata-wrappers

Conversation

@digaobarbosa

@digaobarbosa digaobarbosa commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Description

Source: https://roboflow.slack.com/archives/C05HRBELWVB/p1784711279761049
Public SDK wrappers for updating metadata and tags on existing images. DATAMAN-337 shipped the endpoints and the low-level rfapi.update_image_metadata / batch_update_image_metadata functions, and DATAMAN-345 added the CLI — but there was no public Python surface, so roboflow-product-docs PR 389 had to document the internal rfapi adapter directly.

Fix: thin delegation wrappers following the existing Workspace.get_async_task pattern:

  • workspace.update_image_metadata(image_id, *, metadata=, remove_metadata=, add_tags=, remove_tags=) — sync single image
  • workspace.batch_update_image_metadata(updates, *, wait=False, poll_interval=4.0, timeout=1800.0) — async batch (up to 1,000 images); wait=True polls via the shared poll_until_terminal helper (same as the CLI's --poll) and returns the final task status including per-image failedItems
  • project.update_image_metadata(...) — convenience alias passing the project's workspace slug (the endpoint is workspace-scoped; verified against the backend that batch has no project/filter parameters, so batch stays on Workspace)

No client-side validation: the server is the source of truth and its errors (invalid tag/key, mutual exclusions, 1,000 cap, duplicate ids) surface as RoboflowError with the API's own message and hint. Docstrings publish automatically via mkdocstrings.

Also adds tests/manual/demo_image_metadata.py, a self-cleaning manual smoke script for staging.

Type of change

  • New feature

How has this change been tested?

  • Full unit suite: 874 tests, OK (6 new tests covering delegation args, error propagation, no-wait enqueue response, wait=True polling via polling URL, and task-id fallback polling)
  • ruff + mypy clean
  • Live staging E2E (model-evaluation-workspace/penguin-finder): single update, project alias, batch no-wait + get_async_task, batch wait=True with a bogus id returning succeeded: 2, failed: 1 with the bogus id in failedItems, server validation errors surfacing as RoboflowError, and CLI regression (roboflow image metadata single/batch/error paths) — all green, test data cleaned up

Will the change affect Universe?

No

Any specific deployment considerations

None — SDK-only, no new dependencies.

Docs

  • Docs updated? Follow-up: roboflow-product-docs PR 389 will be updated to use these wrappers instead of rfapi imports. CHANGELOG entry included here.

Add workspace.update_image_metadata / workspace.batch_update_image_metadata
and a project.update_image_metadata alias, wrapping the existing rfapi
functions so updating metadata on existing images no longer requires
importing the internal adapter. Batch supports wait=True via the shared
poll_until_terminal helper. Validation stays server-side; errors surface
as RoboflowError with the API's message.
Comment thread tests/manual/demo_image_metadata.py Fixed
Comment thread tests/manual/demo_image_metadata.py Fixed
Comment thread tests/manual/demo_image_metadata.py Fixed
Comment thread tests/manual/demo_image_metadata.py Fixed
Comment thread tests/manual/demo_image_metadata.py Fixed
Comment thread tests/manual/demo_image_metadata.py Fixed
Comment thread tests/manual/demo_image_metadata.py Fixed
Comment thread tests/manual/demo_image_metadata.py Fixed
CodeQL flags printing response dicts derived from api_key-tainted calls
as clear-text logging of sensitive data. Assert on the responses and
print static status lines instead.
@digaobarbosa digaobarbosa self-assigned this Jul 22, 2026
@digaobarbosa
digaobarbosa requested a review from a team July 22, 2026 12:01
@digaobarbosa
digaobarbosa marked this pull request as ready for review July 22, 2026 12:02
@digaobarbosa
digaobarbosa merged commit 000d195 into main Jul 22, 2026
16 checks passed
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.

3 participants