Skip to content

Implement issue management - #2043

Merged
mrobers1982 merged 1 commit into
developfrom
pnoirel/PLT-2586-issue-management
Mar 18, 2026
Merged

Implement issue management#2043
mrobers1982 merged 1 commit into
developfrom
pnoirel/PLT-2586-issue-management

Conversation

@lb-pno

@lb-pnolb-pno commented Feb 12, 2026

Copy link
Copy Markdown
Contributor

Description

Adds full programmatic support for Issues, Comments, and Issue Categories. Issues can be pinned to specific data row locations (Image, PDF, Text, Video).

Usage Example

This is the standard flow for most users:

project=client.get_project("<ID>")
# Create a category and an issue pinned to an imagecat=project.create_issue_category(name="Quality", description="Quality-related issues")
issue=project.create_issue(
content="Misaligned box",
data_row_id="<DR_ID>",
category_id=cat.id,
position=ImageIssuePosition(x=100, y=200)
)
# Comment and Resolveissue.create_comment(content="Acknowledged.")
issue.resolve()

Deep Dive: All Supported Positions

Click to see exhaustive examples for PDF, Text, and Video
# PDF (%)PdfIssuePosition(x=0.5, y=0.75, page=2)
# Text (Char range)TextIssuePosition(text_block_id="b1", start_char_index=10, end_char_index=25)
# Video (Multiple frames/paths)VideoIssuePosition(frames=[
VideoFrameRange(start=5, end=11, x=450, y=300, end_x=500, end_y=350),
VideoFrameRange(start=20, end=25, x=100, y=100)
])

Implementation Note

Used Pydantic (_CamelCaseMixin) instead of DbObject because the backend GraphQL mutations for Issues use typed input objects incompatible with the legacy ORM's auto-generation.

Fixes # (issue)

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Document change (fix typo or modifying any markdown files, code comments or anything in the examples folder only)

All Submissions

  • Have you followed the guidelines in our Contributing document?
  • Have you provided a description?
  • Are your changes properly formatted?

New Feature Submissions

  • Does your submission pass tests?
  • Have you added thorough tests for your new feature?
  • Have you commented your code, particularly in hard-to-understand areas?
  • Have you added a Docstring?

Changes to Core Features

  • Have you written new tests for your core changes, as applicable?
  • Have you successfully run tests with your changes locally?
  • Have you updated any code comments, as applicable?

Note

Medium Risk
Adds new GraphQL mutation/query flows (mostly experimental=True) and new typed position serialization/deserialization, so failures would primarily be API/compatibility issues rather than affecting existing flows.

Overview
Adds first-class Issue Management APIs to the Python SDK. Projects can now create_issue, get_issues (cursor-paginated with filters), get_issue, and delete_issues, while Issue objects support update, resolve/reopen, delete, and comment CRUD (create_comment, comments, Comment.update, Comment.delete).

Introduces typed issue pinning via new IssuePosition models for image/PDF/text/video (with serialization + deserialization), plus IssueCategory CRUD and new Sphinx docs and exports in labelbox.__init__. Includes comprehensive unit + integration test coverage for the new GraphQL-backed workflows (all marked experimental=True).

Written by Cursor Bugbot for commit c6f03f4. This will update automatically on new commits. Configure here.

@lb-pno

Copy link
Copy Markdown
ContributorAuthor

Full API Reference with Examples

Issue Categories

project=client.get_project("<PROJECT_ID>")
# Createcategory=project.create_issue_category(
name="Quality",
description="Quality-related issues",
)
# List allcategories=project.get_issue_categories()
# Updatecategory=category.update(name="Renamed", description="New description")
# Deletecategory.delete()

Issues

fromlabelboximportIssueStatus, ImageIssuePosition, VideoIssuePosition, VideoFrameRange# Create -- minimalissue=project.create_issue(
content="General quality issue",
data_row_id="<DATA_ROW_ID>",
)
# Create -- with label, category, and positionissue=project.create_issue(
content="Bounding box is misaligned",
data_row_id="<DATA_ROW_ID>",
label_id="<LABEL_ID>",
category_id=category.id,
position=ImageIssuePosition(x=100, y=200),
)
# Also accepts DataRow/Label/IssueCategory objects directlyissue=project.create_issue(
content="Using objects instead of IDs",
data_row_id=data_row, # DataRow objectlabel_id=label, # Label objectcategory_id=category, # IssueCategory object
)
# Fetch with filters (returns PaginatedCollection)forissueinproject.get_issues(status=IssueStatus.OPEN):
print(issue.friendly_id, issue.content)
# Other available filtersproject.get_issues(
data_row_id="<DATA_ROW_ID>",
category_id="<CATEGORY_ID>",
created_by_ids=["<USER_ID>"],
content="search text",
)
# Fetch single issueissue=project.get_issue("<ISSUE_ID>")
# Update (only provided fields are changed)issue=issue.update(content="Updated text")
issue=issue.update(category_id="<NEW_CATEGORY_ID>")
# Resolve / Reopenissue=issue.resolve()
issue=issue.reopen()
# Lazy-loaded related objects (each makes an API call)data_row=issue.data_row() # Optional[DataRow]label=issue.label() # Optional[Label]category=issue.category() # Optional[IssueCategory]# Delete singleissue.delete()
# Bulk deleteproject.delete_issues(["<ISSUE_ID_1>", "<ISSUE_ID_2>"])

Comments

# Createcomment=issue.create_comment(content="I agree, this needs fixing")
# List all comments on an issuecomments=issue.comments()
# Updatecomment=comment.update(content="Revised comment")
# Deletecomment.delete()

Video Position Variants

# Single frameVideoIssuePosition(frames=[
VideoFrameRange(start=5, end=5, x=100, y=200)
])
# Contiguous range (stationary pin)VideoIssuePosition(frames=[
VideoFrameRange(start=5, end=11, x=450, y=300)
])
# Contiguous range (moving pin)VideoIssuePosition(frames=[
VideoFrameRange(start=5, end=11, x=450, y=300, end_x=500, end_y=350)
])
# Multiple separated rangesVideoIssuePosition(frames=[
VideoFrameRange(start=5, end=11, x=450, y=300),
VideoFrameRange(start=20, end=25, x=100, y=100),
])

@lb-pno
lb-pnoforce-pushed the pnoirel/PLT-2586-issue-management branch from 7663610 to d295441CompareFebruary 12, 2026 01:13
@lb-pno
lb-pnoforce-pushed the pnoirel/PLT-2586-issue-management branch from 9d55f6d to 2282f98CompareFebruary 12, 2026 01:47
@lb-pno
lb-pnoforce-pushed the pnoirel/PLT-2586-issue-management branch from 2282f98 to 2bcc661CompareFebruary 12, 2026 02:14
@lb-pno
lb-pnoforce-pushed the pnoirel/PLT-2586-issue-management branch from 2bcc661 to a8fcd12CompareFebruary 15, 2026 19:53
Co-authored-by: Cursor <cursoragent@cursor.com>
@lb-pno
lb-pnoforce-pushed the pnoirel/PLT-2586-issue-management branch from a8fcd12 to c6f03f4CompareFebruary 15, 2026 20:07
@lb-pno
lb-pno marked this pull request as ready for review February 23, 2026 22:33
@lb-pno
lb-pno requested a review from a team as a code ownerFebruary 23, 2026 22:33

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Comment threadlibs/labelbox/src/labelbox/schema/issue.py
@mrobers1982
mrobers1982 merged commit 78cfe93 into developMar 18, 2026
26 of 46 checks passed
@mrobers1982
mrobers1982 deleted the pnoirel/PLT-2586-issue-management branch March 18, 2026 13:13
Sign up for freeto 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.

2 participants

@lb-pno@mrobers1982