def test_prepare_document(db_conn, vases_table): schema = vases_schema create_test_data_set(db_conn, vases_table) data = { 'id': 'ZdhhJQ9U9YJaanmfMEpm05qc', 'name': ' celestial ', 'shape': 'round', 'plants': [ { 'species': 'zzplant', 'quantity': 2 }, { 'species': 'rubbertree', 'quantity': 1 }, ], 'soil': { 'color': 'black' } } result, errors = util.prepare_document(schema, data, db_conn) assert not errors result = omit(result, ( 'id', 'modified', 'created', )) assert result == omit(data, ('id', ))
def test_prepare_row(db_conn): schema = vases_schema create_test_data_set(db_conn) data = { 'id': uuid.uuid4(), 'name': ' celestial ', 'shape': 'round', 'plants': [ { 'species': 'zzplant', 'quantity': 2 }, { 'species': 'rubbertree', 'quantity': 1 }, ], 'soil': { 'color': 'black' } } result, errors = util.prepare_row(db_conn, schema, data) assert not errors result = omit(result, ( 'id', 'modified', 'created', )) assert result == omit(data, ('id', ))
def instance_entities(data): """ Given a kind and some json, call insert on that kind and return the results. A little safer. """ fields = ('id', 'created', 'modified', 'entity_id', 'previous_id', 'status', 'available') entities = [] if 'cards' in data: for card_data in data['cards']: kind = card_data.get('kind') if kind in card_map: entities.push( card_map[kind](omit(card_data, fields)) ) if 'units' in data: entities = entities + [ Unit(omit(unit_data, fields)) for unit_data in data['units'] ] if 'subjects' in data: entities = entities + [ Subject(omit(subject_data, fields)) for subject_data in data['subjects'] ] return entities
def instance_new_entity(data): """ Save as above, but a little safer. """ fields = ('id', 'created', 'modified', 'entity_id', 'previous_id', 'status', 'available') if 'card' in data: return Card(omit(data['card'], fields)) # TODO-1 This needs to also get the right card kind... elif 'unit' in data: return Unit(omit(data['unit'], fields)) elif 'set' in data: return Set(omit(data['set'], fields))
def update(self, data): """ Overwrite update method to remove password. """ data = omit(data, ("password",)) return super().update(data)
def instance_post_facade(data): """ Create the correct kind of post based on the `kind` field. """ data = omit(data, ('id', 'created', 'modified')) return instance(data)
def instance_post_facade(data): """ Create the correct kind of post based on the `kind` field. """ data = omit(data, ("id", "created", "modified")) return instance(data)
def insert_document(schema, data, db_conn): """ Create a new document. Return document and errors if failed. """ data = omit(data, ('id', 'created', 'modified')) return save_document(schema, data, db_conn)
def create_post_facade(db_conn, data): """ Create the correct kind of post based on the `kind` field. """ data = omit(data, ('id', 'created', 'modified')) model = instance(data) return model.save(db_conn)
def test_prepare_document(db_conn, vases_table): schema = vases_schema create_test_data_set(db_conn, vases_table) data = { 'id': 'ZdhhJQ9U9YJaanmfMEpm05qc', 'name': ' celestial ', 'shape': 'round', 'plants': [ {'species': 'zzplant', 'quantity': 2}, {'species': 'rubbertree', 'quantity': 1}, ], 'soil': {'color': 'black'} } result, errors = util.prepare_document(schema, data, db_conn) assert not errors result = omit(result, ('id', 'modified', 'created',)) assert result == omit(data, ('id',))
def instance_new_entity(data): """ Given a kind and some json, call insert on that kind and return the results. A little safer. """ fields = ('id', 'created', 'modified', 'entity_id', 'previous_id', 'status', 'available') if 'card' in data: kind = data['card'].get('kind') if kind in card_map: return card_map[kind](omit(data['card'], fields)) elif 'unit' in data: return Unit(omit(data['unit'], fields)) elif 'set' in data: return Set(omit(data['set'], fields))
def insert(cls, data): """ Create a new model instance. Return model and errors if failed. """ assert isinstance(data, dict) data = omit(data, ('id', 'created', 'modified')) instance = cls(data) return instance.save()
def test_add_default_fields(): schema = vases_schema data = {} data2 = util.add_default_fields(schema, data) data2 = omit(data2, ('id', 'created', 'modified',)) assert data2 == { 'plants': [], 'shape': 'round', 'soil': {'color': 'brown'}, }
def update(self, data): """ Update the model in the database. Return model and errors if failed. """ assert isinstance(data, dict) data = omit(data, ('id', 'created', 'modified')) extend(self.data, data) return self.save()
def update_user(prev_data, data, db_conn): """ Overwrite update method to remove password. """ schema = user_schema data = omit(data, ('password',)) data, errors = update_document(schema, prev_data, data, db_conn) if not errors: add_user_to_es(data) return data, errors
def test_omit(): """ Expect to omit given keys and return a new dict. """ d = {'a': 1, 'b': 2, 'c': 3, 'd': 4} assert util.omit(d, ('a', 'c')) == { 'b': 2, 'd': 4, }
def update_document(schema, prev_data, data, db_conn): """ Update the document in the database. Return document and errors if failed. NOTICE: `prev_data` should be the _return_ of `insert_document`, not the originally provided data. """ data = omit(data, ('id', 'created', 'modified')) data = extend({}, prev_data, data) return save_document(schema, data, db_conn)
def list_posts(params, db_conn): """ Get a list of posts in Sagefy. """ skip = params.get('skip') or 0 limit = params.get('limit') or 10 params = omit(params, ( 'skip', 'limit', )) query = (r.table(post_schema['tablename']).filter(params).order_by( r.asc('created')).skip(skip).limit(limit)) return list(query.run(db_conn))
def update_post(prev_data, data, db_conn): """ Update an existing post. """ schema = get_post_schema(data) data2 = omit(data, ('id', 'created', 'modified')) data2 = extend({}, prev_data, data2) data, errors = validate_post(data2, db_conn) if errors: return data, errors data, errors = update_document(schema, prev_data, data, db_conn) if not errors: add_post_to_es(data, db_conn) return data, errors
def insert_row(db_conn, schema, query, data): """ Validate a row, then insert the row. """ data = omit(data, ('id', 'created', 'modified')) # TODO-2 is it possible to have postgres do this work of # validating/preparing? data, errors = prepare_row(db_conn, schema, data) if errors: return None, errors data = bundle_fields(schema, data) data = convert_fields_to_pgjson(data) # TODO-1 fix this data, errors = save_row(db_conn, query, data) return data, errors
def insert(cls, db_conn, data): """ When a user creates a new version, don't accept certain fields. Also, find the previous_id. """ data = omit(data, ('status', 'available')) if 'entity_id' in data: latest = cls.get_latest_accepted(db_conn, data['entity_id']) data['previous_id'] = latest['id'] return super().insert(db_conn, data)
def test_add_default_fields(): schema = vases_schema data = {} data2 = util.add_default_fields(schema, data) data2 = omit(data2, ( 'id', 'created', 'modified', )) assert data2 == { 'plants': [], 'shape': 'round', 'soil': { 'color': 'brown' }, }
def create_topic_route(request): """ Create a new topic. The first post (or proposal) must be provided. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) # ## STEP 1) Create post and topic (and entity) instances topic_data = request['params'].get('topic') post_data = request['params'].get('post') if not topic_data: return 400, { 'errors': [{ 'name': 'topic', 'message': 'Missing topic data.' }], 'ref': 'zknSd46f2hRNjSjVHCg6YLwN' } if not post_data: return 400, { 'errors': [{ 'name': 'post', 'message': 'Missing post data.' }], 'ref': 'Qki4oWX4nTdNAjYI8z5iNawr' } topic_data = omit(topic_data, ('id', 'created', 'modified')) topic_data['user_id'] = current_user['id'] topic_data, topic_errors = validate_topic(topic_data, db_conn) post_data = omit(post_data, ( 'id', 'created', 'modified', )) post_data['user_id'] = current_user['id'] post_data['topic_id'] = topic_data['id'] post_ = instance_post_facade(post_data) post_kind = post_['kind'] if post_kind == 'proposal': entity = instance_new_entity(request['params']) entity_kind = get_kind(request['params']) post_['entity_version'] = { 'id': entity['id'], 'kind': entity_kind, } # ## STEP 2) Validate post and topic (and entity) instances errors = prefix_error_names('topic.', topic_errors) errors = errors + prefix_error_names('post.', post_.validate(db_conn)) if post_kind == 'proposal': errors = (errors + prefix_error_names('entity.', entity.validate(db_conn))) if len(errors): return 400, {'errors': errors, 'ref': 'TAY5pX3ghWBkSIVGTHzpQySa'} # ## STEP 3) Save post and topic (and entity) topic_data, topic_errors = insert_topic(topic_data, db_conn) post_['topic_id'] = topic_data['id'] post_.save(db_conn) if post_kind == 'proposal': entity.save(db_conn) # ## STEP 4) Add author as a follower insert_follow( { 'user_id': current_user['id'], 'entity': { 'id': topic_data['id'], 'kind': 'topic', } }, db_conn) # TODO-2 also follow the entity automatically IF needed # ## STEP 5) Send out any needed notices send_notices(db_conn, entity_id=topic_data['entity']['id'], entity_kind=topic_data['entity']['kind'], notice_kind='create_topic', notice_data={ 'user_name': current_user['name'], 'topic_name': topic_data['name'], 'entity_kind': topic_data['entity']['kind'], 'entity_name': topic_data['entity']['id'], }) if post_kind == 'proposal': send_notices(db_conn, entity_id=topic_data['entity']['id'], entity_kind=topic_data['entity']['kind'], notice_kind='create_proposal', notice_data={ 'user_name': current_user['name'], 'topic_name': topic_data['name'], 'entity_kind': topic_data['entity']['kind'], 'entity_name': topic_data['entity']['id'], }) # ## STEP 5) Return response return 200, {'topic': deliver_topic(topic_data), 'post': post_.deliver()}
def create_post_route(request, topic_id): """ Create a new post on a given topic. Proposal: must include entity (card, unit, or set) information. Vote: must refer to a valid proposal. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) topic = get_topic({'id': topic_id}, db_conn) if not topic: return 404, { 'errors': [{ 'name': 'topic_id', 'message': c('no_topic'), }], 'ref': 'PCSFCxsJtnlP0x9WzbPoKcwM', } # ## STEP 1) Create post (and entity) instances post_data = request['params'].get('post') if not post_data: return 400, { 'errors': [{ 'name': 'post', 'message': 'Missing post data.', }], 'ref': 'ykQpZwJKq54MTCxgkx0p6baW' } post_data = omit(post_data, ( 'id', 'created', 'modified', )) post_data['user_id'] = current_user['id'] post_data['topic_id'] = topic_id post_ = instance_post_facade(post_data) post_kind = post_['kind'] if post_kind == 'proposal': entity = instance_new_entity(request['params']) entity_kind = get_kind(request['params']) post_['entity_version'] = { 'id': entity['id'], 'kind': entity_kind, } # ## STEP 2) Validate post (and entity) instances errors = prefix_error_names('post.', post_.validate(db_conn)) if post_kind == 'proposal': errors = (errors + prefix_error_names('entity.', entity.validate(db_conn))) if len(errors): return 400, {'errors': errors, 'ref': 'tux33ztgFj9ittSpS7WKIkq7'} # ## STEP 3) Save post (and entity) post_.save(db_conn) if post_kind == 'proposal': entity.save(db_conn) # ## STEP 4) Add author as a follower insert_follow( { 'user_id': current_user['id'], 'entity': { 'id': topic['id'], 'kind': 'topic', } }, db_conn) # TODO-2 also follow the entity # ## STEP 5) Make updates based on proposal / vote status if post_kind == 'proposal': update_entity_status(db_conn, post_) if post_kind == 'vote': proposal = Proposal.get(db_conn, id=post_['replies_to_id']) update_entity_status(db_conn, proposal) # ## STEP 6) Send notices if post_kind == 'proposal': send_notices(db_conn, entity_id=topic['entity']['id'], entity_kind=topic['entity']['kind'], notice_kind='create_proposal', notice_data={ 'user_name': current_user['name'], 'topic_name': topic['name'], 'entity_kind': topic['entity']['kind'], 'entity_name': topic['entity']['id'], }) # ## STEP 7) Return response return 200, {'post': post_.deliver()}
def create_topic_route(request): """ Create a new topic. The first post (or proposal) must be provided. """ current_user = get_current_user(request) if not current_user: return abort(401) # ## STEP 1) Create post and topic (and entity) instances topic_data = request['params'].get('topic') post_data = request['params'].get('post') if not topic_data: return 400, { 'errors': [{ 'name': 'topic', 'message': 'Missing topic data.' }], 'ref': 'zknSd46f2hRNjSjVHCg6YLwN' } if not post_data: return 400, { 'errors': [{ 'name': 'post', 'message': 'Missing post data.' }], 'ref': 'Qki4oWX4nTdNAjYI8z5iNawr' } topic_data = omit(topic_data, ('id', 'created', 'modified')) topic_data['user_id'] = current_user['id'] topic = Topic(topic_data) post_data = omit(post_data, ('id', 'created', 'modified',)) post_data['user_id'] = current_user['id'] post_data['topic_id'] = topic['id'] post_ = instance_post_facade(post_data) post_kind = post_['kind'] if post_kind == 'proposal': entity = instance_new_entity(request['params']) entity_kind = get_kind(request['params']) post_['entity_version'] = { 'id': entity['id'], 'kind': entity_kind, } # ## STEP 2) Validate post and topic (and entity) instances errors = prefix_error_names('topic.', topic.validate()) errors = errors + prefix_error_names('post.', post_.validate()) if post_kind == 'proposal': errors = errors + prefix_error_names('entity.', entity.validate()) if len(errors): return 400, { 'errors': errors, 'ref': 'TAY5pX3ghWBkSIVGTHzpQySa' } # ## STEP 3) Save post and topic (and entity) topic.save() post_.save() if post_kind == 'proposal': entity.save() # ## STEP 4) Add author as a follower Follow.insert({ 'user_id': current_user['id'], 'entity': { 'id': topic['id'], 'kind': 'topic', } }) # TODO-2 also follow the entity automatically IF needed # ## STEP 5) Send out any needed notifications send_notices( entity_id=topic['entity']['id'], entity_kind=topic['entity']['kind'], notice_kind='create_topic', notice_data={ 'user_name': current_user['name'], 'topic_name': topic['name'], 'entity_kind': topic['entity']['kind'], 'entity_name': topic['entity']['id'], } ) # ## STEP 5) Return response return 200, {'topic': topic.deliver(), 'post': post_.deliver()}
def create_post_route(request, topic_id): """ Create a new post on a given topic. Proposal: must include entity (card, unit, or set) information. Vote: must refer to a valid proposal. """ current_user = get_current_user(request) if not current_user: return abort(401) topic = Topic.get(id=topic_id) if not topic: return 404, { 'errors': [{ 'name': 'topic_id', 'message': c('no_topic'), }], 'ref': 'PCSFCxsJtnlP0x9WzbPoKcwM', } # ## STEP 1) Create post (and entity) instances post_data = request['params'].get('post') if not post_data: return 400, { 'errors': [{ 'name': 'post', 'message': 'Missing post data.', }], 'ref': 'ykQpZwJKq54MTCxgkx0p6baW' } post_data = omit(post_data, ('id', 'created', 'modified',)) post_data['user_id'] = current_user['id'] post_data['topic_id'] = topic_id post_ = instance_post_facade(post_data) post_kind = post_['kind'] if post_kind == 'proposal': entity = instance_new_entity(request['params']) entity_kind = get_kind(request['params']) post_['entity_version'] = { 'id': entity['id'], 'kind': entity_kind, } # ## STEP 2) Validate post (and entity) instances errors = prefix_error_names('post.', post_.validate()) if post_kind == 'proposal': errors = errors + prefix_error_names('entity.', entity.validate()) if len(errors): return 400, { 'errors': errors, 'ref': 'tux33ztgFj9ittSpS7WKIkq7' } # ## STEP 3) Save post (and entity) post_.save() if post_kind == 'proposal': entity.save() # ## STEP 4) Add author as a follower Follow.insert({ 'user_id': current_user['id'], 'entity': { 'id': topic['id'], 'kind': 'topic', } }) # TODO-2 also follow the entity # ## STEP 5) Make updates based on proposal / vote status if post_kind == 'proposal': update_entity_status(post_) if post_kind == 'vote': proposal = Proposal.get(id=post_['replies_to_id']) update_entity_status(proposal) # ## STEP 6) Return response return 200, {'post': post_.deliver()}