def fin(): print("finalizer subidea_thread_phase_1") test_session.delete(l_r_1) test_session.add(IdeaLink(source=root_idea, target=subidea_1)) test_session.flush()
def save_idea(request): """Update this idea. In case the ``parentId`` is changed, handle all ``IdeaLink`` changes and send relevant ideas on the socket.""" discussion = request.context user_id = authenticated_userid(request) permissions = request.permissions idea_id = request.matchdict['id'] idea_data = json.loads(request.body) # Idea.default_db.execute('set transaction isolation level read committed') # Special items in TOC, like unsorted posts. if idea_id in ['orphan_posts']: return {'ok': False, 'id': Idea.uri_generic(idea_id)} idea = Idea.get_instance(idea_id) db = idea.db if not idea: raise HTTPNotFound("No such idea: %s" % (idea_id)) if isinstance(idea, RootIdea): raise HTTPBadRequest("Cannot edit root idea.") if (idea.discussion_id != discussion.id): raise HTTPBadRequest( "Idea from discussion %s cannot be saved from different discussion (%s)." % (idea.discussion_id, discussion.id)) context = idea.get_instance_context(request=request) for key, attr_name in langstring_fields.items(): if key in idea_data: current = getattr(idea, attr_name) ls_data = idea_data[key] # TODO: handle legacy string instance? subcontext = idea.get_collection_context(key, context) if current: if ls_data: current.update_from_json(ls_data, context=subcontext, permissions=permissions) else: current.delete() elif ls_data: current = LangString.create_from_json(ls_data, context=subcontext) setattr(idea, attr_name, current._instance) new_parent_id = idea_data.get('parentId', None) if new_parent_id: # TODO: Make sure this is sent as a list! # Actually, use embedded links to do this properly... new_parent_ids = {new_parent_id} old_parent_ids = { Idea.uri_generic(l.source_id) for l in idea.source_links } if new_parent_ids != old_parent_ids: added_parent_ids = new_parent_ids - old_parent_ids removed_parent_ids = old_parent_ids - new_parent_ids added_parents = [Idea.get_instance(id) for id in added_parent_ids] current_parents = idea.get_parents() removed_parents = [ p for p in current_parents if p.uri() in removed_parent_ids ] if None in added_parents: missing = [ id for id in added_parent_ids if not Idea.get_instance(id) ] raise HTTPNotFound("Missing parentId %s" % (','.join(missing))) if not idea.has_permission_req(P_ASSOCIATE_IDEA): raise HTTPUnauthorized("Cannot associate idea " + idea.uri()) for parent in added_parents + removed_parents: if not parent.has_permission_req(P_ASSOCIATE_IDEA): raise HTTPUnauthorized("Cannot associate parent idea " + idea.uri()) old_ancestors = set() new_ancestors = set() for parent in current_parents: old_ancestors.add(parent) old_ancestors.update(parent.get_all_ancestors()) kill_links = { l for l in idea.source_links if Idea.uri_generic(l.source_id) in removed_parent_ids } order = idea_data.get('order', 0.0) for parent in added_parents: if kill_links: link = kill_links.pop() db.expire(link.source, ['target_links']) link.copy(True) link.order = order link.source = parent else: link = IdeaLink(source=source, target=idea, order=order) db.add(link) db.expire(parent, ['target_links']) order += 1.0 for link in kill_links: db.expire(link.source, ['target_links']) kill_links.is_tombstone = True db.expire(idea, ['source_links']) db.flush() for parent in idea.get_parents(): new_ancestors.add(parent) new_ancestors.update(parent.get_all_ancestors()) for ancestor in new_ancestors ^ old_ancestors: ancestor.send_to_changes() else: order = idea_data.get('order', None) if order is not None: new_parent_id = Idea.get_database_id(new_parent_id) parent_links = [ link for link in idea.source_links if link.source_id == new_parent_id ] assert len(parent_links) == 1 parent_links[0].order = idea_data.get('order', 0.0) if 'subtype' in idea_data: idea.rdf_type = idea_data['subtype'] idea.send_to_changes() return {'ok': True, 'id': idea.uri()}