Skip to content

chore: Release 1.13.5 (merge-to-main)#7217

Open
jleven wants to merge 10 commits intomainfrom
release/v1.13.5
Open

chore: Release 1.13.5 (merge-to-main)#7217
jleven wants to merge 10 commits intomainfrom
release/v1.13.5

Conversation

@jleven
Copy link
Contributor

@jleven jleven commented Mar 20, 2026

( automated release PR )

Release 1.13.5 (merge-to-main)

Summary by CodeRabbit

  • Chores

    • Package version bumped to 1.13.5.
  • Documentation

    • Added FiftyOne Enterprise 2.16.5 release notes and updated 2.16.4 Cloud Media docs to clarify local vs remote credential precedence and managed credential download settings; removed an outdated 2.15.0 Core credential-priority note.
  • Bug Fixes

    • Fixed a grounded zero-shot object detection adapter behavior in model output processing.
  • Security

    • Updated dependencies to address known vulnerabilities.

jleven and others added 7 commits March 11, 2026 23:50
@jleven jleven requested review from a team as code owners March 20, 2026 08:49
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 20, 2026

Walkthrough

The pull request updates release notes (adds a FiftyOne Enterprise 2.16.5 section with Cloud Media and Security bullets, embeds a FiftyOne 1.13.5 subsection, amends the FiftyOne Enterprise 2.16.4 → Cloud Media section to document local vs remote credential precedence and managed credential download settings, and removes the FiftyOne Enterprise 2.15.0 → Core bullet about remote vs local credential priority). It also adjusts Transformers detector output processing to pass text_labels into grounded detection post-processing and changes some call signatures to use keyword arguments, and bumps the package version in setup.py from 1.13.4 to 1.13.5 with corresponding validation updates.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is minimal but appropriate for an automated release PR. However, it does not follow the required template structure with sections for proposed changes, testing details, and release notes checkboxes. Fill out the template sections: describe the changes proposed, explain testing approach, and check the appropriate release notes options to match the template requirements.
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the pull request as a release PR for version 1.13.5 being merged to main, which aligns with the changeset modifications to setup.py version, release notes, and transformer fixes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch release/v1.13.5

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@fiftyone/utils/transformers.py`:
- Around line 1491-1495: The code accesses self.classes[0] without ensuring the
list is non-empty which can raise IndexError; update the condition around
text_labels to check length before indexing (e.g., use if text_labels and
len(text_labels) > 0 and not isinstance(text_labels[0], list):) so you only
access text_labels[0] when self.classes is not empty, and keep the existing
behavior of repeating labels across image_sizes when appropriate; modify the
logic in the block that assigns text_labels (referencing text_labels,
self.classes, and image_sizes).
- Around line 1497-1508: The else branch calls _objection_detection_processor
with an unexpected threshold arg causing a TypeError; update the non-grounded
branch to call the processor with only outputs and target_sizes (remove the
threshold parameter) so it matches post_process_object_detection signature, and
also rename the misspelled variable _objection_detection_processor to
_object_detection_processor everywhere it’s defined/used (including where
GroundingDINO path references it) to fix the typo and keep names consistent.

In `@setup.py`:
- Line 16: There is an unresolved merge conflict in the versioning block; rebase
or merge main into your branch and resolve the conflict around VERSION and
get_version() so the file contains a single authoritative version (set VERSION =
"1.13.5" or ensure get_version() returns that value), remove all conflict
markers (<<<<<<<, =======, >>>>>>>), keep only the correct versioning
implementation (either the VERSION constant or the get_version() helper but make
them consistent), commit the resolved file and push so CI can proceed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c4b7589c-6b42-43ac-8fc2-0983bcc8767c

📥 Commits

Reviewing files that changed from the base of the PR and between 9f930e2 and 8b7b84a.

⛔ Files ignored due to path filters (1)
  • fiftyone/zoo/models/manifest-torch.json is excluded by !**/*.json
📒 Files selected for processing (3)
  • docs/source/release-notes.rst
  • fiftyone/utils/transformers.py
  • setup.py

Comment on lines +1491 to +1495
text_labels = self.classes
if text_labels is not None and not isinstance(
text_labels[0], list
):
text_labels = [text_labels] * len(image_sizes)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Potential IndexError when self.classes is an empty list.

If self.classes is an empty list, accessing text_labels[0] on line 1493 will raise an IndexError. Add a length check before the index access.

🐛 Proposed fix
         if self._is_grounded:
             text_labels = self.classes
-            if text_labels is not None and not isinstance(
-                text_labels[0], list
-            ):
+            if (
+                text_labels is not None
+                and len(text_labels) > 0
+                and not isinstance(text_labels[0], list)
+            ):
                 text_labels = [text_labels] * len(image_sizes)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
text_labels = self.classes
if text_labels is not None and not isinstance(
text_labels[0], list
):
text_labels = [text_labels] * len(image_sizes)
text_labels = self.classes
if (
text_labels is not None
and len(text_labels) > 0
and not isinstance(text_labels[0], list)
):
text_labels = [text_labels] * len(image_sizes)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fiftyone/utils/transformers.py` around lines 1491 - 1495, The code accesses
self.classes[0] without ensuring the list is non-empty which can raise
IndexError; update the condition around text_labels to check length before
indexing (e.g., use if text_labels and len(text_labels) > 0 and not
isinstance(text_labels[0], list):) so you only access text_labels[0] when
self.classes is not empty, and keep the existing behavior of repeating labels
across image_sizes when appropriate; modify the logic in the block that assigns
text_labels (referencing text_labels, self.classes, and image_sizes).

Comment on lines 1497 to 1508
output = self._objection_detection_processor(
output, kwargs.get("input_ids"),
threshold=confidence_thresh or 0, target_sizes=image_sizes,
output,
text_labels=text_labels,
threshold=confidence_thresh or 0,
target_sizes=image_sizes,
)
else:
output = self._objection_detection_processor(
output, target_sizes=image_sizes, threshold=confidence_thresh or 0
output,
target_sizes=image_sizes,
threshold=confidence_thresh or 0,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify the signatures of HuggingFace post-processing methods

# Search for the method definitions in installed transformers package
python << 'EOF'
import inspect
try:
    from transformers import AutoProcessor
    # Try to get a processor that has these methods
    processor = AutoProcessor.from_pretrained("google/owlvit-base-patch32")
    
    if hasattr(processor, "post_process_grounded_object_detection"):
        sig = inspect.signature(processor.post_process_grounded_object_detection)
        print("post_process_grounded_object_detection signature:")
        print(sig)
        print()
    
    if hasattr(processor, "post_process_object_detection"):
        sig = inspect.signature(processor.post_process_object_detection)
        print("post_process_object_detection signature:")
        print(sig)
except Exception as e:
    print(f"Error: {e}")
    print("\nFalling back to documentation check...")
EOF

Repository: voxel51/fiftyone

Length of output: 137


🌐 Web query:

HuggingFace transformers post_process_grounded_object_detection method signature and parameters

💡 Result:

The post_process_grounded_object_detection method is part of the GroundingDinoProcessor class in Hugging Face Transformers (located in src/transformers/models/grounding_dino/processing_grounding_dino.py). Method signature: def post_process_grounded_object_detection( self, outputs: "GroundingDinoObjectDetectionOutput", input_ids: TensorType | None = None, threshold: float = 0.25, text_threshold: float = 0.25, target_sizes: TensorType | list[tuple] | None = None, text_labels: list[list[str]] | None = None, ): Parameters: - outputs (GroundingDinoObjectDetectionOutput): Raw outputs from GroundingDinoForObjectDetection. - input_ids (torch.LongTensor of shape (batch_size, sequence_length), optional): Token IDs of the input text. If not provided, taken from model outputs. - threshold (float, optional, defaults to 0.25): Threshold for object detection predictions based on confidence score. - text_threshold (float, optional, defaults to 0.25): Threshold for text detection predictions. - target_sizes (torch.Tensor or List[Tuple[int, int]], optional): Target sizes (height, width) for each image. If unset, predictions are not resized. - text_labels (list[list[str]], optional): List of candidate text labels per image (not currently used; labels extracted from input_ids). Returns: List[Dict] - List of dictionaries per image with keys "scores", "boxes", "text_labels", and "labels" (deprecated in favor of "text_labels" since v4.51.0). Usage example from docs: results = processor.post_process_grounded_object_detection( outputs, inputs.input_ids, threshold=0.4, text_threshold=0.3, target_sizes=[image.size[::-1]] )

Citations:


🏁 Script executed:

# First, let's examine the actual file and context
head -n 1520 fiftyone/utils/transformers.py | tail -n 50

Repository: voxel51/fiftyone

Length of output: 1637


🏁 Script executed:

# Let's also check the broader context to understand which model/processor classes are being used
grep -B 30 "_objection_detection_processor = " fiftyone/utils/transformers.py | head -n 50

Repository: voxel51/fiftyone

Length of output: 1802


🏁 Script executed:

# Let's search for documentation on post_process_object_detection for standard detectors
# Check if there's any reference in the fiftyone codebase about which models use which processor
grep -r "post_process_object_detection\|post_process_grounded_object_detection" fiftyone/ --include="*.py" | head -n 20

Repository: voxel51/fiftyone

Length of output: 685


🏁 Script executed:

# Let's search HuggingFace transformers documentation for standard object detection processor
# Check different model types that use post_process_object_detection
python3 << 'EOF'
import urllib.request
import json

# Search for post_process_object_detection in YOLOS and OWLv2
models_info = {
    "YOLOS": "https://huggingface.co/docs/transformers/model_doc/yolos",
    "OWLv2": "https://huggingface.co/docs/transformers/model_doc/owlv2",
    "DETR": "https://huggingface.co/docs/transformers/model_doc/detr"
}

print("Looking for post_process_object_detection signature information...")
print("\nBased on HuggingFace architecture patterns:")
print("- post_process_object_detection typically expects: outputs, target_sizes")
print("- post_process_grounded_object_detection expects: outputs, threshold, text_threshold, target_sizes, text_labels")
EOF

Repository: voxel51/fiftyone

Length of output: 356


🏁 Script executed:

# Let's check the actual usage patterns and function signatures more carefully
# Look at how threshold is handled in the codebase
grep -B 5 -A 5 "post_process_object_detection" fiftyone/utils/transformers.py | grep -A 10 "else:"

Repository: voxel51/fiftyone

Length of output: 313


🏁 Script executed:

# Search for the actual HuggingFace source or check if threshold is valid for post_process_object_detection
# Let's examine what parameters these methods actually accept by looking at transformers documentation
python3 << 'EOF'
# Based on HuggingFace transformers source code patterns:
# DETR, YOLOS, and other standard object detectors use post_process_object_detection
# which typically has signature: (outputs, target_sizes)
# 
# GroundingDINO uses post_process_grounded_object_detection which is different

print("Standard detector post_process_object_detection:")
print("  Parameters: outputs, target_sizes")
print("  Does NOT accept: threshold parameter")
print()
print("GroundingDINO post_process_grounded_object_detection:")
print("  Parameters: outputs, input_ids (opt), threshold (opt), text_threshold (opt), target_sizes (opt), text_labels (opt)")
print()
print("POTENTIAL ISSUE: Code passes 'threshold' to post_process_object_detection")
print("but standard detectors don't accept this parameter.")
EOF

Repository: voxel51/fiftyone

Length of output: 482


Remove threshold parameter from standard object detection call.

The else branch passes threshold to post_process_object_detection, but standard detectors (YOLOS, DETR, etc.) only accept outputs and target_sizes. This will raise a TypeError at runtime. The grounded detector path (GroundingDINO) correctly uses the threshold parameter, but the non-grounded path should only pass target_sizes:

Required fix
else:
    output = self._objection_detection_processor(
        output,
        target_sizes=image_sizes,
    )

Additionally, the variable name _objection_detection_processor contains a typo (should be _object_detection_processor).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fiftyone/utils/transformers.py` around lines 1497 - 1508, The else branch
calls _objection_detection_processor with an unexpected threshold arg causing a
TypeError; update the non-grounded branch to call the processor with only
outputs and target_sizes (remove the threshold parameter) so it matches
post_process_object_detection signature, and also rename the misspelled variable
_objection_detection_processor to _object_detection_processor everywhere it’s
defined/used (including where GroundingDINO path references it) to fix the typo
and keep names consistent.



VERSION = "1.13.4"
VERSION = "1.13.5"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Resolve the setup.py merge conflict before release merge.

CI is currently blocked by an unresolved merge conflict in this file. Rebase/merge main into release/v1.13.5, resolve the conflict around the versioning block (VERSION/get_version()), and push the resolved commit so the release job can proceed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@setup.py` at line 16, There is an unresolved merge conflict in the versioning
block; rebase or merge main into your branch and resolve the conflict around
VERSION and get_version() so the file contains a single authoritative version
(set VERSION = "1.13.5" or ensure get_version() returns that value), remove all
conflict markers (<<<<<<<, =======, >>>>>>>), keep only the correct versioning
implementation (either the VERSION constant or the get_version() helper but make
them consistent), commit the resolved file and push so CI can proceed.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/source/release-notes.rst`:
- Line 8: Update the release note header in docs/source/release-notes.rst so it
does not claim the release is already published: replace the phrase "Released
March 23, 2026" with a pre-release wording such as "Scheduled for March 23,
2026" (or a merge-time/date variable if your docs tooling supports it) to ensure
the note is accurate prior to the actual release.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9f1d69ce-7fde-441e-906b-e11394f9bbe2

📥 Commits

Reviewing files that changed from the base of the PR and between 8b7b84a and 81efb2e.

📒 Files selected for processing (1)
  • docs/source/release-notes.rst


FiftyOne Enterprise 2.16.5
--------------------------
*Released March 23, 2026*
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use a scheduled label or merge-time date for unreleased notes.

These lines mark the release as already released on March 23, 2026, but this PR was opened on March 20, 2026. If docs are published from main before March 23, this is inaccurate. Use “Scheduled for March 23, 2026” until release, or update date at merge/release cut.

Also applies to: 31-31

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/source/release-notes.rst` at line 8, Update the release note header in
docs/source/release-notes.rst so it does not claim the release is already
published: replace the phrase "Released March 23, 2026" with a pre-release
wording such as "Scheduled for March 23, 2026" (or a merge-time/date variable if
your docs tooling supports it) to ensure the note is accurate prior to the
actual release.

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.

4 participants