Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix empty set #404

Closed
wants to merge 4 commits into from
Closed

Conversation

lucemia
Copy link
Contributor

@lucemia lucemia commented Dec 3, 2014

for issue #403

for test case. I am curious about whether to create a new test case test_save_entity_w_transaction_list_value and included #399.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.01%) when pulling 79ff1a3 on lucemia:property-with-empty-list into 5457564 on GoogleCloudPlatform:master.

@tseaver
Copy link
Contributor

tseaver commented Dec 3, 2014

If we aren't going to marshall the value, then we should probably be preventing assignment of it in __setitem__() and update(). Otherwise, we might need to fabricate a custom entity_value to be used for this case.

@lucemia
Copy link
Contributor Author

lucemia commented Dec 3, 2014

@tseaver
preventing assignment via __setitem__ and update() looks will fail in the following case..

entity = Entity(dataset, 'test')
entity['a'] = []
entity['a'].append(1) 

@tseaver
Copy link
Contributor

tseaver commented Dec 5, 2014

Silently dropping the attribute-with-empty-list during save() will mean that it is missing when loaded again.

@dhermes
Copy link
Contributor

dhermes commented Dec 19, 2014

Is this PR dead? It's certainly silent.

@tseaver
Copy link
Contributor

tseaver commented Dec 19, 2014

@dhermes how would you envision dealing with an entity where the property value (in Python) is an empty list? We can't marshall that to the protobuf "normally", becase an empty list_value field doesn't satisfy the criterion that the property have a value set.

I posted in #403 (comment) a reference to an alternate implementation, which creates an entity_value for the property with an empty list, but didn't create a PR from that branch.

@dhermes
Copy link
Contributor

dhermes commented Dec 19, 2014

@tseaver Sorry I wasn't trying to claim #403 is dead / fixed, just this PR. I looked at the alternate implementation, but am not a big fan of things like '_gcloud:empty_list'.

Has anyone been able to send an empty list using just proto objects?

@dhermes
Copy link
Contributor

dhermes commented Dec 21, 2014

@tseaver I commented on the original issue as well, but I think the "correct" / simplest fix would be to change the code you focus on in your solution:

    elif attr == 'list_value':
        if len(val) == 0:
            continue
        l_pb = value_pb.list_value
        for item in val:

@tseaver
Copy link
Contributor

tseaver commented Dec 21, 2014

We would need to document that some values (empty lists, None, etc.) cannot be saved to the back-end.

@dhermes
Copy link
Contributor

dhermes commented Dec 21, 2014

I agree. I wonder if the datastore folks also document that it's not possible to do?

@lucemia
Copy link
Contributor Author

lucemia commented Dec 22, 2014

If we document this behavior,

We would need to document that some values (empty lists, None, etc.) cannot be saved to the back-end.

I guess we don't need to have '_gcloud:empty_list' ?

@dhermes
Copy link
Contributor

dhermes commented Dec 22, 2014

Just a tiny code change which never adds the property and documents that empty lists aren't stored.

@lucemia
Copy link
Contributor Author

lucemia commented Dec 22, 2014

@dhermes
if I fixed the helpers.py to

elif attr == 'list_value':
        if len(val) == 0:
            return
        l_pb = value_pb.list_value
        for item in val:
            i_pb = l_pb.add()
            _set_protobuf_value(i_pb, item)
    else:  # scalar, just assign
        setattr(value_pb, attr, val)

it will still raise the following exception

Traceback (most recent call last):
  File "test.py", line 26, in <module>
    entity.save()
  File "/Users/david/repos/gcloud-python/gcloud/datastore/entity.py", line 245, in save
    exclude_from_indexes=self.exclude_from_indexes())
  File "/Users/david/repos/gcloud-python/gcloud/datastore/connection.py", line 482, in save_entity
    result = self.commit(dataset_id, mutation)
  File "/Users/david/repos/gcloud-python/gcloud/datastore/connection.py", line 382, in commit
    datastore_pb.CommitResponse)
  File "/Users/david/repos/gcloud-python/gcloud/datastore/connection.py", line 95, in _rpc
    data=request_pb.SerializeToString())
  File "/Users/david/anaconda/lib/python2.7/site-packages/google/protobuf/internal/python_message.py", line 813, in SerializeToString
    self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
google.protobuf.message.EncodeError: Message api.services.datastore.CommitRequest is missing required fields: mutation.insert_auto_id[0].property[0].value

so I check the list value in connection.py https://github.com/GoogleCloudPlatform/gcloud-python/pull/404/files

@dhermes
Copy link
Contributor

dhermes commented Dec 22, 2014

Right, adding the property should never happen. My bad for indicating otherwise.

@coveralls
Copy link

Coverage Status

Coverage remained the same when pulling 9e2d1f0 on lucemia:property-with-empty-list into 5457564 on GoogleCloudPlatform:master.

@lucemia
Copy link
Contributor Author

lucemia commented Dec 28, 2014

The test case is added :)

@coveralls
Copy link

Coverage Status

Coverage remained the same when pulling 15a507e on lucemia:property-with-empty-list into 5457564 on GoogleCloudPlatform:master.

@@ -643,7 +643,8 @@ def test_save_entity_wo_transaction_w_upsert(self):
'commit',
])
http = conn._http = Http({'status': '200'}, rsp_pb.SerializeToString())
result = conn.save_entity(DATASET_ID, key_pb, {'foo': u'Foo'})
result = conn.save_entity(DATASET_ID, key_pb,
{'foo': u'Foo', 'bar': []})

This comment was marked as spam.

@dhermes
Copy link
Contributor

dhermes commented Dec 30, 2014

You should also add a test for save_entities. This makes me think the change should happen in the to_protobuf method.

Also, for such a small change, we have quite a few do-nothing commits in this PR. Do you mind squashing into a single commit and re-writing your history? I'm happy to help if you like.

@lucemia
Copy link
Contributor Author

lucemia commented Dec 31, 2014

@dhermes
I find a workaround today only need to modify the _set_protobuf_value in helpers.py.

elif attr == 'list_value':
        l_pb = value_pb.list_value
        if len(val) == 0:
            x = l_pb.add()
            l_pb.remove(x)

or

if len(val) == 0:
    l_pb.extend([])

@dhermes
Copy link
Contributor

dhermes commented Dec 31, 2014

@lucemia That's great! I'm a little confused as to why it works. Wouldn't we be better clearing value_pb from its parent?


Also, provided we can agree on this proposed workaround, want to just close this PR and open a new one (so as not to have to worry about re-writing history)?

Make sure to polish up and run tox locally before committing / submitting the PR.

@lucemia
Copy link
Contributor Author

lucemia commented Dec 31, 2014

Wouldn't we be better clearing value_pb from its parent?

Thx @dhermes

I am now very sure which parent you mention, would you mind to provide more detail therefore I can add it to my new PR?

I will open a new PR with new workaround and close current one.

@dhermes
Copy link
Contributor

dhermes commented Dec 31, 2014

Well the issue is that the only thing _set_protobuf_value receives is an instance of datastore_v1_pb2.Value (via value_pb).

However, we actually want to remove a datastore_v1_pb2.Property (which owns value_pb) from a datastore_v1_pb2.Entity object such as an auto insert in a mutation:

>>> insert_auto = mutation.insert_auto_id.add()
>>> prop = insert_auto.property.add()
>>> # Do some stuff
>>> # Oops didn't mean to add the property
>>>  insert_auto.property.remove(prop)

Unfortunately, it appears that there is no public API for retrieving a parent, so our best way forward may be a re-thinking of which data gets passed to _set_protobuf_value.

I took a stab with the non-public API provided by protobuf and it is not very pleasant. (Though it's also irrelevant since we can't rely on unsupported behavior.)


No need to close this one until we get the right solution actually sorted out.

@lucemia
Copy link
Contributor Author

lucemia commented Dec 31, 2014

@dhermes

I created two branch and did some test with the following code.

conn = datastore.connection.Connection(credentials)
result = conn.save_entity(DATASET_ID, key_pb, {
    'foo': u'Foo',
    'bar': None,
    'bar1': []
})

While saving a empty list to cloud datastore:

method1 fix the _set_protobuf_value

lucemia@5e4d5b9
this method will save the property with null value.

screen shot 2014-12-31 at 12 20 20 pm

method2 fix the save_entity

lucemia@2c3defa
this method will drop the property.

screen shot 2014-12-31 at 12 19 40 pm

I also test the same condition on ndb (with remote_api_shell), the ndb will drop repeated property with empty list (like method2). So I think the original approach (fix the save_entity) works better. If it sounds make sense, I will rebase the branch property-with-empty-list.

@lucemia
Copy link
Contributor Author

lucemia commented Jan 5, 2015

@dhermes
It seems to me that _set_protobuf_list will face the same issue as _set_protobuf_value.
It cannot delete Property itself due to the protobuf api limit..., can it ?

@dhermes
Copy link
Contributor

dhermes commented Jan 5, 2015

It seems unlikely that this is fully possible without a re-write involving changing the arguments passed, potentially in multiple functions.

@lucemia
Copy link
Contributor Author

lucemia commented Jan 8, 2015

@dhermes
For PropertyFilter usage, does that make sense to pass an empty list to Value?
If not, I think I can focus on solve the Property usage case first.

@dhermes
Copy link
Contributor

dhermes commented Jan 8, 2015

ISTM both problems can be solved in the same way but maybe I'm missing something.

You can show the fix for Property and we can discuss?

@lucemia
Copy link
Contributor Author

lucemia commented Jan 8, 2015

To solve the Property, I come up with two ways. (am I missing something?)

the original code in connection.py

for name, value in properties.items():
            prop = insert.property.add()
            # Set the name of the property.
            prop.name = name

            # Set the appropriate value.
            helpers._set_protobuf_value(prop.value, value)

            if name in exclude_from_indexes:
                if not isinstance(value, list):
                    prop.value.indexed = False

                for sub_value in prop.value.list_value:
                    sub_value.indexed = False

1. check the value type in first place

for name, value in properties.items():
    if isinstance(value, list) and len(value) == 0:
          continue
    prop = insert.property.add()
    # ....

2. define a new helper function

     for name, value in properties.items():
            helpers._set_protobuf_property(insert.property, name, value, 
                                           name in exclude_from_indexes)

@dhermes
Copy link
Contributor

dhermes commented Jan 8, 2015

Number 2. seems a much more robust solution

@lucemia
Copy link
Contributor Author

lucemia commented Jan 8, 2015

ok i will create a PR with sol2. Thanks!

@dhermes
Copy link
Contributor

dhermes commented Jan 8, 2015

Closing in favor of #512

@dhermes dhermes closed this Jan 8, 2015
@dhermes dhermes added the api: datastore Issues related to the Datastore API. label Dec 31, 2015
atulep pushed a commit that referenced this pull request Apr 6, 2023
* chore(deps): update all dependencies

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* revert

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
Co-authored-by: Anthonios Partheniou <[email protected]>
atulep pushed a commit that referenced this pull request Apr 6, 2023
* chore(deps): update all dependencies

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* revert

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
Co-authored-by: Anthonios Partheniou <[email protected]>
atulep pushed a commit that referenced this pull request Apr 18, 2023
* chore(deps): update all dependencies

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* revert

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
Co-authored-by: Anthonios Partheniou <[email protected]>
parthea pushed a commit that referenced this pull request Jun 4, 2023
* feat: added font_family to document.proto
feat: added ImageQualityScores message to document.proto
feat: added PropertyMetadata and EntityTypeMetadata to document_schema.proto

PiperOrigin-RevId: 486975621

Source-Link: googleapis/googleapis@398c9f9

Source-Link: googleapis/googleapis-gen@7cd1f5f
Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiN2NkMWY1ZjRlNDM1Nzc3Y2I4MjRhZjI2OGRjOGQzNzEzNDYxM2U2YSJ9

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* Update constraints-3.7.txt

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
Co-authored-by: Holt Skinner <[email protected]>
parthea pushed a commit that referenced this pull request Jun 4, 2023
Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
parthea pushed a commit that referenced this pull request Jun 4, 2023
Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
parthea pushed a commit that referenced this pull request Jul 6, 2023
Source-Link: https://togithub.com/googleapis/synthtool/commit/25083af347468dd5f90f69627420f7d452b6c50e
Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:e6cbd61f1838d9ff6a31436dfc13717f372a7482a82fc1863ca954ec47bff8c8
parthea pushed a commit that referenced this pull request Aug 15, 2023
Source-Link: googleapis/synthtool@d2871d9
Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:b2dc5f80edcf5d4486c39068c9fa11f7f851d9568eea4dcba130f994ea9b5e97

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
parthea pushed a commit that referenced this pull request Sep 20, 2023
* feat: support per-entity search and autocomplete
feat: add model get API
feat: support new filter syntax for recommendation
feat: expose A/B experiment info in search response
docs: keep the API doc up-to-date with recent changes

PiperOrigin-RevId: 522675546

Source-Link: googleapis/googleapis@81b0808

Source-Link: googleapis/googleapis-gen@e950439
Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiZTk1MDQzOWNkMGQ0ODZhYjhkMmIzMjY3MmI1NGMwYTZiNjQ1MTQyMCJ9

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* feat: add model service
feat: support per-entity search and autocomplete
feat: support new filter syntax for recommendation
feat: expose A/B experiment info in search response
docs: keep the API doc up-to-date with recent changes

PiperOrigin-RevId: 522675951

Source-Link: googleapis/googleapis@f149e91

Source-Link: googleapis/googleapis-gen@c4538a8
Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiYzQ1MzhhODg4ZDJlYzEzY2U3MTljMWExYWE5ZGM3ZGU1YjE3Mzc1YSJ9

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* feat: add merchant center link service
feat: support per-entity search and autocomplete
feat: expose facets and product counts in autocomplete
feat: add model get API
feat: allow cascaded deletion on primary product
feat: support new filter syntax for recommendation
feat: expose A/B experiment info in search response
docs: keep the API doc up-to-date with recent changes

PiperOrigin-RevId: 523140513

Source-Link: googleapis/googleapis@4a9f933

Source-Link: googleapis/googleapis-gen@ffb754a
Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiZmZiNzU0YTdkMmNkNzkzODBmYjVjY2ZkMzNhMWMwOTA4ZGJiNjJhNSJ9

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

---------

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
vchudnov-g pushed a commit that referenced this pull request Sep 20, 2023
* docs(samples): adds training phrases sample

* docs(samples): fixed lint

* docs(samples): ignored auto-foratting

Co-authored-by: Anthonios Partheniou <[email protected]>
vchudnov-g pushed a commit that referenced this pull request Sep 20, 2023
parthea added a commit that referenced this pull request Sep 22, 2023
* chore: update to gapic-generator-python 1.5.0

feat: add support for `google.cloud.<api>.__version__`
PiperOrigin-RevId: 484665853

Source-Link: googleapis/googleapis@8eb249a

Source-Link: googleapis/googleapis-gen@c8aa327
Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiYzhhYTMyN2I1ZjQ3ODg2NWZjM2ZkOTFlM2MyNzY4ZTU0ZTI2YWQ0NCJ9

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* update version in gapic_version.py

* add .release-please-manifest.json with correct version

* add owlbot.py to exclude generated gapic_version.py

* set manifest to true in .github/release-please.yml

* add release-please-config.json

* chore: Update to gapic-generator-python 1.6.0

feat(python): Add typing to proto.Message based class attributes

feat(python): Snippetgen handling of repeated enum field

PiperOrigin-RevId: 487326846

Source-Link: googleapis/googleapis@da380c7

Source-Link: googleapis/googleapis-gen@61ef576
Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiNjFlZjU3NjJlZTY3MzFhMGNiYmZlYTIyZmQwZWVjZWU1MWFiMWM4ZSJ9

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* feat: new APIs added to reflect updates to the filestore service

- Add ENTERPRISE Tier
- Add snapshot APIs: RevertInstance, ListSnapshots, CreateSnapshot, DeleteSnapshot, UpdateSnapshot
- Add multi-share APIs: ListShares, GetShare, CreateShare, DeleteShare, UpdateShare
- Add ConnectMode to NetworkConfig (for Private Service Access support)
- New status codes (SUSPENDED/SUSPENDING, REVERTING/RESUMING)
- Add SuspensionReason (for KMS related suspension)
- Add new fields to Instance information: max_capacity_gb, capacity_step_size_gb, max_share_count, capacity_gb, multi_share_enabled

PiperOrigin-RevId: 487492758

Source-Link: googleapis/googleapis@5be5981

Source-Link: googleapis/googleapis-gen@ab0e217
Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiYWIwZTIxN2Y1NjBjYzJjMWFmYzExNDQxYzJlYWI2YjY5NTBlZmQyYiJ9

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* update path to snippet metadata json

* chore: Update gapic-generator-python to v1.6.1

PiperOrigin-RevId: 488036204

Source-Link: googleapis/googleapis@08f275f

Source-Link: googleapis/googleapis-gen@555c094
Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiNTU1YzA5NDVlNjA2NDllMzg3MzlhZTY0YmM0NTcxOWNkZjcyMTc4ZiJ9

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* feat: added Location API methods
docs: updated comments

PiperOrigin-RevId: 489094434

Source-Link: googleapis/googleapis@71673d8

Source-Link: googleapis/googleapis-gen@1017723
Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiMTAxNzcyMzJkNDIwMDA2NjEwYWU5ZmI3NDBkOWYxM2VmZTk3NWNiOSJ9

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
Co-authored-by: Anthonios Partheniou <[email protected]>
parthea pushed a commit that referenced this pull request Sep 22, 2023
Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
parthea pushed a commit that referenced this pull request Oct 21, 2023
* docs: Fix formatting of request arg in docstring

chore: Update gapic-generator-python to v1.9.1
PiperOrigin-RevId: 518604533

Source-Link: googleapis/googleapis@8a085ae

Source-Link: googleapis/googleapis-gen@b2ab4b0
Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiYjJhYjRiMGEwYWUyOTA3ZTgxMmMyMDkxOThhNzRlMDg5OGFmY2IwNCJ9

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

---------

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
parthea pushed a commit that referenced this pull request Oct 21, 2023
Source-Link: https://togithub.com/googleapis/synthtool/commit/eaef28efd179e6eeb9f4e9bf697530d074a6f3b9
Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:f8ca7655fa8a449cadcabcbce4054f593dcbae7aeeab34aa3fcc8b5cf7a93c9e
parthea added a commit that referenced this pull request Oct 22, 2023
* chore(deps): update all dependencies

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* revert

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
Co-authored-by: Anthonios Partheniou <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: datastore Issues related to the Datastore API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants