Implement issue management by lb-pno · Pull Request #2043 · Labelbox/labelbox-python
Full API Reference with Examples
Issue Categories
project = client.get_project("<PROJECT_ID>") # Create category = project.create_issue_category( name="Quality", description="Quality-related issues", ) # List all categories = project.get_issue_categories() # Update category = category.update(name="Renamed", description="New description") # Delete category.delete()
Issues
from labelbox import IssueStatus, ImageIssuePosition, VideoIssuePosition, VideoFrameRange # Create -- minimal issue = project.create_issue( content="General quality issue", data_row_id="<DATA_ROW_ID>", ) # Create -- with label, category, and position issue = 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 directly issue = project.create_issue( content="Using objects instead of IDs", data_row_id=data_row, # DataRow object label_id=label, # Label object category_id=category, # IssueCategory object ) # Fetch with filters (returns PaginatedCollection) for issue in project.get_issues(status=IssueStatus.OPEN): print(issue.friendly_id, issue.content) # Other available filters project.get_issues( data_row_id="<DATA_ROW_ID>", category_id="<CATEGORY_ID>", created_by_ids=["<USER_ID>"], content="search text", ) # Fetch single issue issue = 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 / Reopen issue = 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 single issue.delete() # Bulk delete project.delete_issues(["<ISSUE_ID_1>", "<ISSUE_ID_2>"])
Comments
# Create comment = issue.create_comment(content="I agree, this needs fixing") # List all comments on an issue comments = issue.comments() # Update comment = comment.update(content="Revised comment") # Delete comment.delete()
Video Position Variants
# Single frame VideoIssuePosition(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 ranges VideoIssuePosition(frames=[ VideoFrameRange(start=5, end=11, x=450, y=300), VideoFrameRange(start=20, end=25, x=100, y=100), ])