Skip to content

Commit

Permalink
Object.get_or_create: merge repeated fields instead of overwriting
Browse files Browse the repository at this point in the history
  • Loading branch information
snarfed committed Jan 16, 2025
1 parent 525a26f commit 8796b9e
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 3 deletions.
5 changes: 5 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,11 @@ def get_or_create(cls, id, authed_as=None, **props):

if set(props.keys()) & set(('as2', 'bsky', 'mf2', 'raw')):
obj.clear()

# merge repeated fields
for field in 'feed', 'copies', 'labels', 'notify', 'users':
getattr(obj, field).extend(props.pop(field, []))

obj.populate(**{
k: v for k, v in props.items()
if v and not isinstance(getattr(Object, k), ndb.ComputedProperty)
Expand Down
6 changes: 5 additions & 1 deletion protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,11 @@ def receive(from_cls, obj, authed_as=None, internal=False, received_at=None):
error(f'Actor {actor} is opted out or blocked', status=204)

# write Object to datastore
orig_props = obj.to_dict()
orig_props = {
**obj.to_dict(),
# structured properties
'copies': obj.copies,
}
obj = Object.get_or_create(id, new=obj.new, changed=obj.changed,
authed_as=actor, **orig_props)

Expand Down
16 changes: 14 additions & 2 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -637,11 +637,23 @@ def check(obj1, obj2):
obj7 = Object.get_or_create('http://b.ee/ff', as2={'a': 'b'}, mf2={'c': 'd'},
source_protocol='web')
Object.get_or_create('http://b.ee/ff', authed_as='http://b.ee/ff',
users=[ndb.Key(Web, 'me')])
users=[ndb.Key(Web, 'me')], labels=['feed'],
copies=[Target(protocol='ui', uri='http://foo')])
self.assert_object('http://b.ee/ff', as2={'a': 'b'}, mf2={'c': 'd'},
users=[ndb.Key(Web, 'me')],
users=[ndb.Key(Web, 'me')], labels=['feed'],
copies=[Target(protocol='ui', uri='http://foo')],
source_protocol='web')

# repeated properties should merge, not overwrite
Object.get_or_create('http://b.ee/ff', authed_as='http://b.ee/ff',
users=[ndb.Key(Web, 'you')], labels=['user'],
copies=[Target(protocol='ui', uri='http://bar')])
self.assert_object('http://b.ee/ff', as2={'a': 'b'}, mf2={'c': 'd'},
users=[ndb.Key(Web, 'me'), ndb.Key(Web, 'you')],
labels=['feed', 'user'], source_protocol='web',
copies=[Target(protocol='ui', uri='http://foo'),
Target(protocol='ui', uri='http://bar')])

def test_get_or_create_auth_check(self):
Object(id='fake:foo', our_as1={'author': 'fake:alice'},
source_protocol='fake').put()
Expand Down

0 comments on commit 8796b9e

Please sign in to comment.