Skip to content

Add support for file search - #321

Open
loookashow wants to merge 1 commit into
feat/file-tagsfrom
feat/file-search
Open

Add support for file search#321
loookashow wants to merge 1 commit into
feat/file-tagsfrom
feat/file-search

Conversation

@loookashow

Copy link
Copy Markdown
Contributor

Part 2 of 2, splitting #319 per @dmitry-mukhin's request. This is the file search half, stacked on top of the file tags PR (base branch feat/file-tags) — search's TagsFilter reuses validate_tags from the tags module, so it depends on that PR. Review/merge the tags PR first; GitHub will retarget this one to main automatically.

The diff below is search-only. Once the tags PR merges, this shows against main.

Exposes file searchPOST /files/search/.

What's included

  • Uploadcare.search_files(), returning one typed page, and Uploadcare.iterate_search_files(), which walks pages (limit = total to yield, request_limit = page size, as elsewhere in the SDK).
  • FilesAPI.search().
  • Typed requests via FileSearchRequest (query, phrase, exact, datetime_uploaded, size, is_image, tags + fuzziness / sort), also accepting a plain dict. All documented API constraints are validated locally before a request is made.
  • FileSearchResponse (next, previous, total, per_page, results), each result a FileSearchInfo with a SearchHighlight.
  • New ucare search_files command.

Notable decisions

  • Pagination never requests the response's absolute next URL — the REST client attaches credentials to any URL it is given, so next is used only as a has-more signal and the offset is computed locally, clamped to the 1000-result window.
  • total is not used as a stop condition, since the API documents it as approximate for large result sets.
  • iterate_search_files() warns when asked to page through a filter-only request without sort, whose result order the API leaves undefined.

Testing

  • Functional tests use unittest.mock for request shape and hand-authored cassettes for response parsing.
  • Integration tests (tests/integration/test_file_search.py) cover conditions, modifiers, highlight, appdata and pagination against the live API. Search indexing is asynchronous (~10s), which the tests poll for and the docs now note.
  • One documentation correction from live verification: highlight for a filter-only match arrives as an empty object rather than being absent as the reference states.

make lint is clean; the full functional + Django suite passes (466 tests); the search integration suite passes against a live project.

🤖 Generated with Claude Code

Expose the REST API v0.7 POST /files/search/ endpoint in the SDK.

- Uploadcare.search_files(), returning one typed page, and
  Uploadcare.iterate_search_files(), which walks pages
- FilesAPI.search()
- Typed requests: FileSearchRequest with query, phrase, exact,
  datetime_uploaded, size, is_image and tags conditions plus the fuzziness
  and sort modifiers, built from SearchPhrase, SearchExact, DatetimeRange,
  SizeRange, TagsFilter and SearchSort. A plain dict in the same shape works
  too
- FileSearchResponse with next, previous, total, per_page and results, each
  result a FileSearchInfo carrying a SearchHighlight
- ucare search_files command

Requests are validated locally against the documented API constraints before
any request is made, so a malformed search fails fast with a clear message.

Paging never requests the response's next URL: it is an absolute,
server-supplied URL, and the REST client attaches credentials to whatever URL
it is given. next is used only as a has-more signal and the offset is computed
locally, clamped so no request exceeds the 1000-result window. total is not
used as a stop condition because the API documents it as approximate for large
result sets.

iterate_search_files() warns when asked to page through a filter-only request
without sort, whose result order the API leaves undefined.

Search indexing is asynchronous (~10s), which the integration tests poll for
and the docs note. highlight for a filter-only match arrives as an empty
object rather than being absent as the reference states.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Aug 5, 2026

Copy link
Copy Markdown

@loookashow

Copy link
Copy Markdown
Contributor Author

@dmitry-mukhin please review

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.

1 participant