Add support for file tags - #320
Open
loookashow wants to merge 7 commits into
Open
Conversation
Expose the REST API v0.7 file tags endpoints in the SDK.
- TagsAPI (uploadcare.tags_api) with get/replace/update, covering GET, PUT
and PATCH on /files/{uuid}/tags/
- File: tags property plus get_tags(), set_tags() and update_tags()
- tags argument for Uploadcare.upload(), upload_files() and
multipart_upload(), sent as the comma-separated tags form field
- tags in FileInfo
- ucare get_file_tags, set_file_tags and update_file_tags commands, and a
--tags option for ucare upload
- TagValidationError for tags exceeding the API limits
Tags are normalized before validation, the way the API normalizes them, so
values it would accept after its own normalization are not rejected locally.
update() with no arguments sends an empty body, since the endpoint documents
both fields as optional; requiring at least one of --add/--delete is a CLI
concern instead. The 50-tags-per-file limit does not apply to PATCH delete,
which is a candidate list where absent tags are ignored.
Uploads from url do not support tags upstream, so passing them raises
InvalidParamError rather than dropping them silently.
FileInfo.model_dump(), and therefore File.info, now always contains a tags
key: None for responses that do not report tags, [] for files without any.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
dmitry-mukhin
requested changes
Aug 5, 2026
Comment on lines
+323
to
+331
| """Replaces all file tags by requesting Uploadcare API. | ||
|
|
||
| Passing an empty list clears the tags:: | ||
|
|
||
| >>> file_ = uploadcare.file('a771f854-c2cb-408a-8c36-71af77811f3b') | ||
| >>> file_.set_tags(['cat', 'animal']) | ||
| UpdateFileTagsResponse(tags=['cat', 'animal'], added=['cat', 'animal'], deleted=[]) | ||
|
|
||
| """ |
Member
There was a problem hiding this comment.
this is hard to parse.
so it clears the tags and adds the ones in arg?
Co-authored-by: Dmitry Mukhin <dm@uploadcare.com>
Co-authored-by: Dmitry Mukhin <dm@uploadcare.com>
Co-authored-by: Dmitry Mukhin <dm@uploadcare.com>
Co-authored-by: Dmitry Mukhin <dm@uploadcare.com>
Co-authored-by: Dmitry Mukhin <dm@uploadcare.com>
The web edits renamed TagsAPI.replace to set but left File.set_tags, the tag tests, and the internal response_classes key on the old name, which broke File.set_tags at runtime. Point them all at set, and reword the set_tags docstring to state it replaces the whole tag set.
|
dmitry-mukhin
approved these changes
Aug 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Part 1 of 2, splitting #319 into reviewable pieces per @dmitry-mukhin's request. This is the file tags half; file search follows in a stacked PR based on this branch (search imports
validate_tagsfrom the tags module, so it has to land on top).Exposes file tags from REST API v0.7. The
Accept: application/vnd.uploadcare-v0.7+jsonheader is already sent (conf.api_versionis0.7), so no header work was needed. Bumps the version to 6.3.0 (the search PR adds to the same changelog section without touching the version again).What's included
TagsAPI(uploadcare.tags_api) mirroringMetadataAPI:get()/replace()/update(), coveringGET/PUT/PATCHon/files/{uuid}/tags/.File: atagsproperty plusget_tags(),set_tags(),update_tags().tagsargument onUploadcare.upload(),upload_files()andmultipart_upload(), sent as the comma-separatedtagsform field.tagsonFileInfo.ucarecommandsget_file_tags,set_file_tags,update_file_tags, and--tagsonucare upload.TagValidationErrorfor tags exceeding the API limits (50 per file, 100 chars, Latin letters/digits/-/_/.).Notable decisions
TagsAPI.update()with no arguments sends an empty body — the endpoint documents both fields as optional. Requiring at least one of--add/--deleteis a CLI-only concern. The 50-tag limit is not applied to PATCHdelete, which is a candidate list where absent tags are ignored.InvalidParamErrorrather than silently dropping them.FileInfo.model_dump()— and thereforeFile.info— now always contains atagskey (Nonewhen the endpoint does not report tags,[]for a file without tags).Testing
unittest.mockfor request shape (VCR matches on method + URI only) and hand-authored cassettes for response parsing.tests/integration/test_file_tags.py,tests/integration/ucare_cli/test_file_tags.py) exercise the whole surface against the live API, creating and deleting their own files and uploading a PNG so they work on projects that restrict uploadable types.File.tagsafter a direct upload fetches the info and returns the stored tags (only multipart leaves itNone).make lintis clean; functional + Django suites pass (310 tests); the tags integration tests pass against a live project (21 tests).🤖 Generated with Claude Code