You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Setting the metadata locally does not cause the instance to make the API call to patch it on the server, and we don't send metadata along with the upload_from_file() call. You need to add a call to blob.patch() to persist the changes to blob.metadata.
To allow mutation of the metadata in-place (as opposed to assigning to it wholesale), we would need a way to detect those mutations, in order to mark it as changed (for a subsequent call to blob.patch() to pick up).
A custom dict class could work for the examples I provided. This would still not make a dict behave as expected tough. Since dicts are mutable, I would expect the following to work:
I think this subclass could work if no setter is defined. An empty metadata object could be set in the Blob constructor. This exposes the metadata as if it is a regular dict. This would break with the current behaviour, where setting metadatais allowed.
The fact that the getter returns a copy is not set in stone. We did it to "protect" the integrity of the actual data own by the class, but didn't think through situations like this.
We don't need a getter, but do need a setter to track changes on the object. Can't have a setter without a getter, so that's just how it's gotta be. (Also, all properties are stored on a non-public attribute called _properties, another reason for a getter.)
@saxenanurag I'm in the middle of reviewing how we are using the ex-apitools code (now in gcloud.streaming), and can see how we should be able to send the patched metadata along with the upload request.
@Prabakaran1410 You don't need to call patch on the blob after upload: since PR #3362, all properties assigned to the blob before upload are passed through.
I had some trouble getting this to work because the metadata was always None (even though I manually added values via the Storage UI). Later I realized I was using bucket.blob("name") rather than bucket.get_blob("name") so the metadata hadn't been loaded. Might help someone else.
Activity
tseaver commentedon Oct 15, 2015
Setting the
metadatalocally does not cause the instance to make the API call to patch it on the server, and we don't send metadata along with theupload_from_file()call. You need to add a call toblob.patch()to persist the changes toblob.metadata.remcohaszing commentedon Oct 15, 2015
I modified the script:
This sets the
ColorandSpammetadata fields, but not theFoofield. There is no warning about this whatsoever.Also there is no documentation on the
Blobclass on how to update metadata.dhermes commentedon Oct 15, 2015
Thanks for reporting. Looking into it now.
dhermes commentedon Oct 15, 2015
Ahhh. This is because the
Blob.metadatagetter returns acopy.deepcopyof the dictionary stored, so doingupdates the copy, not the dictionary actually stored on the
Blob. We should fix this.@tseaver WDYT?
tseaver commentedon Oct 15, 2015
To allow mutation of the
metadatain-place (as opposed to assigning to it wholesale), we would need a way to detect those mutations, in order to mark it as changed (for a subsequent call toblob.patch()to pick up).dhermes commentedon Oct 15, 2015
Right. Custom
dictsubclass?tseaver commentedon Oct 15, 2015
Right, overriding:
__delitem____setitem__clearupdatesetdefaultpoppopitemremcohaszing commentedon Oct 15, 2015
A custom
dictclass could work for the examples I provided. This would still not make a dict behave as expected tough. Since dicts are mutable, I would expect the following to work:If the setter of
blob.metadatawould return this new class, this would no longer refer to the original dict that has been set.remcohaszing commentedon Oct 15, 2015
I think this subclass could work if no setter is defined. An empty metadata object could be set in the
Blobconstructor. This exposes the metadata as if it is a regulardict. This would break with the current behaviour, where settingmetadatais allowed.dhermes commentedon Oct 15, 2015
The fact that the getter returns a copy is not set in stone. We did it to "protect" the integrity of the actual data own by the class, but didn't think through situations like this.
We don't need a getter, but do need a setter to track changes on the object. Can't have a setter without a getter, so that's just how it's gotta be. (Also, all properties are stored on a non-public attribute called
_properties, another reason for a getter.)remcohaszing commentedon Oct 15, 2015
I suppose it could look something like this:
This marks the metadata as modified if it gets edited and ensures the metadata can't be overridden using a setter.
A side effect is that the metadata property is never
None. I personally like that better anyway.saxenanurag commentedon Dec 16, 2015
worked for me. I was able to upload a file and apply the meta data after the file upload.
tseaver commentedon Dec 16, 2015
@saxenanurag I'm in the middle of reviewing how we are using the ex-
apitoolscode (now ingcloud.streaming), and can see how we should be able to send the patched metadata along with the upload request.dhermes commentedon Dec 17, 2015
👍 What he said 😀
4 remaining items
tseaver commentedon Jun 5, 2017
#3362 passes along all non-ACL blob properties with the (initial or only) upload request.
gjkemnitz commentedon Oct 20, 2018
You can work around this bug by creating a completely new dictionary, assigning it to blob.metadata, and doing blob.patch():
Your blob will now have the {'mynewproperty':'awesome'} metadata property in its stored metadata list on GCS.
Prabakaran1410 commentedon Nov 7, 2019
With patch() the metadata of a file is getting updated properly. But this has two operations,
Is there any option to upload the file along with its metadata? this should be a single step process
tseaver commentedon Nov 7, 2019
@Prabakaran1410 You don't need to call
patchon the blob after upload: since PR #3362, all properties assigned to the blob before upload are passed through.paul121 commentedon Jul 30, 2020
I had some trouble getting this to work because the
metadatawas alwaysNone(even though I manually added values via the Storage UI). Later I realized I was usingbucket.blob("name")rather thanbucket.get_blob("name")so the metadata hadn't been loaded. Might help someone else.Fixed failed tests on Kokoro (Natural Language API) [(#1185)](GoogleC…
chore(main): release 2.33.0 (#1185)
chore(deps): update all dependencies (#1185)
fix: Allow mtls sts endpoint for external account token urls. (#1185)
chore(main): release 2.33.0 (#1185)
chore: Update mypy version (#1185)
chore(deps): update all dependencies (#1185)
docs: migrate code from googleapis/python-bigquery (#18303)