Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 2025-06-06 "Search Response Model Improvements" - version 1.14.1

### Fixed
- Enhanced SearchResponse `Object` model to properly handle more fields returned by the Iconik API, including complex nested structures
### Technical Details
This patch improves the SDK's handling of search responses by gathering more fields from the Iconik API and properly deserializing them, especially the critical `_sort` field needed for pagination and consistent ordering.

## 2025-06-04 "Search Enhancements & Field Model Fixes" - version 1.14.0

### Added
Expand Down Expand Up @@ -591,4 +598,4 @@ Note: Previous functionality remains available but will display deprecation warn

## 2023-10-18

- Initial commit (Brant Goddard)
- Initial commit (Brant Goddard)
118 changes: 111 additions & 7 deletions pythonik/models/search/search_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,131 @@

from typing import Any, List, Optional, Dict

from pydantic import BaseModel
from pydantic import BaseModel, Field

from pythonik.models.base import PaginatedResponse
from pythonik.models.files.file import File
from pythonik.models.files.format import Format
from pythonik.models.files.keyframe import Keyframe
from pythonik.models.files.proxy import Proxy


class Highlight(BaseModel):
"""Represents highlighted search results."""

title: Optional[List[str]] = []
# Add other highlight fields as needed


# class FormatMetadata(BaseModel):
# """Metadata specific to a format."""

# format: Optional[str] = None
# # Add other format metadata fields as needed


# class Format(BaseModel):
# """Represents a file format."""

# archive_status: Optional[str] = None
# date_created: Optional[str] = None
# date_deleted: Optional[str] = None
# date_modified: Optional[str] = None
# deleted_by_user: Optional[str] = None
# id: Optional[str] = None
# is_online: Optional[bool] = None
# metadata: Optional[List[FormatMetadata]] = None
# name: Optional[str] = None
# size: Optional[int] = None
# status: Optional[str] = None
# storage_methods: Optional[List[str]] = None
# user_id: Optional[str] = None


class Version(BaseModel):
"""Represents a version of an asset."""

analyze_status: Optional[str] = None
archive_status: Optional[str] = None
created_by_user: Optional[str] = None
date_created: Optional[str] = None
face_recognition_status: Optional[str] = None
has_unconfirmed_persons: Optional[bool] = None
id: Optional[str] = None
is_online: Optional[bool] = None
person_ids: Optional[List[str]] = []
status: Optional[str] = None
transcribe_status: Optional[str] = None
transcribed_languages: Optional[List[str]] = []


class Object(BaseModel):
date_created: Optional[str] = ""
date_modified: Optional[str] = ""
description: Optional[str] = ""
id: Optional[str] = ""
"""Represents an object in the search response."""

# Base fields from original model
date_created: Optional[str] = None
date_modified: Optional[str] = None
description: Optional[str] = None
id: Optional[str] = None
metadata: Optional[Dict[str, Any]] = {}
object_type: Optional[str] = ""
title: Optional[str] = ""
object_type: Optional[str] = None
title: Optional[str] = None
files: Optional[List[File]] = []
proxies: Optional[List[Proxy]] = []
keyframes: Optional[List[Keyframe]] = []

# Additional fields from example response
highlight: Optional[Highlight] = Field(None, alias="_highlight")
sort: Optional[List[Any]] = Field(None, alias="_sort")
analyze_status: Optional[str] = None
ancestor_collections: Optional[List[str]] = []
archive_status: Optional[str] = None
category: Optional[str] = None
created_by_share: Optional[str] = None
created_by_share_user: Optional[str] = None
created_by_user: Optional[str] = None
created_by_user_info: Optional[Any] = None
custom_keyframe: Optional[str] = None
custom_poster: Optional[str] = None
date_deleted: Optional[str] = None
date_imported: Optional[str] = None
date_viewed: Optional[str] = None
deleted_by_user: Optional[str] = None
external_id: Optional[str] = None
external_link: Optional[str] = None
face_recognition_status: Optional[str] = None
file_names: Optional[List[str]] = []
format: Optional[str] = None
formats: Optional[List[Format]] = []
has_unconfirmed_persons: Optional[bool] = None
in_collections: Optional[List[str]] = []
is_blocked: Optional[bool] = None
is_online: Optional[bool] = None
last_archive_restore_date: Optional[str] = None
media_type: Optional[str] = None
original_asset_id: Optional[str] = None
original_segment_id: Optional[str] = None
original_version_id: Optional[str] = None
permissions: Optional[List[str]] = []
person_ids: Optional[List[str]] = []
position: Optional[int] = None
site_name: Optional[str] = None
status: Optional[str] = None
system_domain_id: Optional[str] = None
system_name: Optional[str] = None
time_end_milliseconds: Optional[int] = None
time_start_milliseconds: Optional[int] = None
transcribe_status: Optional[str] = None
transcribed_languages: Optional[List[str]] = []
type: Optional[str] = None
updated_by_user: Optional[str] = None
versions: Optional[List[Version]] = []
versions_number: Optional[int] = None
warning: Optional[str] = None


class SearchResponse(PaginatedResponse):
"""Represents the complete search response."""

facets: Optional[Dict[str, Any]] = {}
objects: Optional[List[Object]] = []