)]}'
{"dragonflow/controller/df_db_objects_refresh.py":[{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"7f5d674dac37da24a1a3ac5c9ef7f028f82a9773","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2015 OpenStack Foundation."},{"line_number":2,"context_line":"# All Rights Reserved."},{"line_number":3,"context_line":"#"},{"line_number":4,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_d0fb9cbf","line":1,"range":{"start_line":1,"start_character":19,"end_line":1,"end_character":20},"updated":"2016-09-26 08:59:25.000000000","message":"6","commit_id":"55b751db7989827c0a064724c11dfb21461f2155"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"1ecb5096609682e0ffe535398033f1bfbafeb7e4","unresolved":false,"context_lines":[{"line_number":30,"context_line":"                 delete_callback):"},{"line_number":31,"context_line":"        \"\"\"Initializes all the callbacks that should be used.\"\"\""},{"line_number":32,"context_line":"        self.obj_type \u003d obj_type"},{"line_number":33,"context_line":"        self.db_read_callback \u003d db_read_callback"},{"line_number":34,"context_line":"        self.read_callback \u003d read_callback"},{"line_number":35,"context_line":"        self.update_callback \u003d update_callback"},{"line_number":36,"context_line":"        self.delete_callback \u003d delete_callback"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_0a80718a","line":33,"range":{"start_line":33,"start_character":13,"end_line":33,"end_character":15},"updated":"2016-09-26 08:16:49.000000000","message":"Consider renaming to cache_read_callback.","commit_id":"55b751db7989827c0a064724c11dfb21461f2155"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"1ecb5096609682e0ffe535398033f1bfbafeb7e4","unresolved":false,"context_lines":[{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def read(self):"},{"line_number":40,"context_line":"        \"\"\"Reads the objects from the database.\"\"\""},{"line_number":41,"context_line":"        for curr_obj in self.db_read_callback():"},{"line_number":42,"context_line":"            self.objects_to_remove[curr_obj.get_id()] \u003d curr_obj"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    def update(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_ea5d0548","line":41,"range":{"start_line":41,"start_character":29,"end_line":41,"end_character":31},"updated":"2016-09-26 08:16:49.000000000","message":"This function returns keys (according to how the object is constructed in df-controller.) yet you treat them as objects.","commit_id":"55b751db7989827c0a064724c11dfb21461f2155"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"7f5d674dac37da24a1a3ac5c9ef7f028f82a9773","unresolved":false,"context_lines":[{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def read(self):"},{"line_number":40,"context_line":"        \"\"\"Reads the objects from the database.\"\"\""},{"line_number":41,"context_line":"        for curr_obj in self.db_read_callback():"},{"line_number":42,"context_line":"            self.objects_to_remove[curr_obj.get_id()] \u003d curr_obj"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    def update(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_a4c331ec","line":41,"range":{"start_line":41,"start_character":29,"end_line":41,"end_character":31},"in_reply_to":"5a8bc5a2_ea5d0548","updated":"2016-09-26 08:59:25.000000000","message":"+1","commit_id":"55b751db7989827c0a064724c11dfb21461f2155"},{"author":{"_account_id":22060,"name":"jingting","email":"kangjingting@huawei.com","username":"jingting"},"change_message_id":"6540a0e0f8acde5bba7a0302402e58b6fb0be71a","unresolved":false,"context_lines":[{"line_number":49,"context_line":"        For every object that exists in both, we update it, and for each"},{"line_number":50,"context_line":"        object that was removed from the DB we mark it for removal."},{"line_number":51,"context_line":"        \"\"\""},{"line_number":52,"context_line":"        for my_object in self.read_callback():"},{"line_number":53,"context_line":"            self.update_callback(my_object)"},{"line_number":54,"context_line":"            obj_id \u003d my_object.get_id()"},{"line_number":55,"context_line":"            self.objects_to_remove.pop(obj_id, None)"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_5adcfd72","line":52,"range":{"start_line":52,"start_character":30,"end_line":52,"end_character":43},"updated":"2016-09-26 11:45:55.000000000","message":"consider rename db_read_callback","commit_id":"55b751db7989827c0a064724c11dfb21461f2155"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"1ecb5096609682e0ffe535398033f1bfbafeb7e4","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        \"\"\""},{"line_number":63,"context_line":"        if self.objects_to_remove:"},{"line_number":64,"context_line":"            for _id, curr_obj in six.iteritems(self.objects_to_remove):"},{"line_number":65,"context_line":"                self.delete_callback(curr_obj)"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_8acf2128","line":65,"updated":"2016-09-26 08:16:49.000000000","message":"Consider clearing objects_to_remove after the loop. Otherwise you may call delete_callback on the same object twice.","commit_id":"55b751db7989827c0a064724c11dfb21461f2155"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"7adc4d25cd298c1dc48aa3232d8a515e86353170","unresolved":false,"context_lines":[{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def read(self):"},{"line_number":38,"context_line":"        \"\"\"Reads the objects from the database.\"\"\""},{"line_number":39,"context_line":"        for curr_id in self.cache_read_ids_callback():"},{"line_number":40,"context_line":"            self.object_ids_to_remove.add(curr_id)"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def update(self):"},{"line_number":43,"context_line":"        \"\"\"Updates existing objects and marks obsolete ones for removal."}],"source_content_type":"text/x-python","patch_set":6,"id":"3a98d1f4_b339dc43","line":40,"range":{"start_line":39,"start_character":0,"end_line":40,"end_character":50},"updated":"2016-09-30 07:11:11.000000000","message":"why not just \n\nself.object_ids_to_remove \u003d set(self.cache_read_ids_callback())","commit_id":"087f531be9d85b6369310d45923fcabfaa6326e2"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"7adc4d25cd298c1dc48aa3232d8a515e86353170","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        The marking is done using the update method, and the removal"},{"line_number":59,"context_line":"        is done by using the relevant callback."},{"line_number":60,"context_line":"        \"\"\""},{"line_number":61,"context_line":"        if self.object_ids_to_remove:"},{"line_number":62,"context_line":"            for curr_id in self.object_ids_to_remove:"},{"line_number":63,"context_line":"                self.cache_delete_id_callback(curr_id)"},{"line_number":64,"context_line":"        self.object_ids_to_remove.clear()"}],"source_content_type":"text/x-python","patch_set":6,"id":"3a98d1f4_13229000","line":61,"range":{"start_line":61,"start_character":0,"end_line":61,"end_character":37},"updated":"2016-09-30 07:11:11.000000000","message":"This check is actually not necessary, the code works just the same as without it.","commit_id":"087f531be9d85b6369310d45923fcabfaa6326e2"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"3486b6a5870d932b56117597cd736e7c022bce67","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        self.object_ids_to_remove \u003d set()"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def read(self):"},{"line_number":38,"context_line":"        \"\"\"Reads the objects from the database.\"\"\""},{"line_number":39,"context_line":"        self.object_ids_to_remove \u003d set(self.cache_read_ids_callback())"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    def update(self):"}],"source_content_type":"text/x-python","patch_set":9,"id":"1a95cdbc_dbfb8145","line":38,"range":{"start_line":38,"start_character":21,"end_line":38,"end_character":47},"updated":"2016-10-10 01:38:26.000000000","message":"I think you mean \"Reads the id of objects from the cache.\"","commit_id":"0c34a4fba2ddd2a76e44e1fc8e65cc9e6d7bb5e9"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"3486b6a5870d932b56117597cd736e7c022bce67","unresolved":false,"context_lines":[{"line_number":41,"context_line":"    def update(self):"},{"line_number":42,"context_line":"        \"\"\"Updates existing objects and marks obsolete ones for removal."},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"        This is done by reading all the current objects from the repository"},{"line_number":45,"context_line":"        and comparing it with the list we got from the database."},{"line_number":46,"context_line":"        For every object that exists in both, we update it, and for each"},{"line_number":47,"context_line":"        object that was removed from the DB we mark it for removal."}],"source_content_type":"text/x-python","patch_set":9,"id":"1a95cdbc_9b8c99db","line":44,"range":{"start_line":44,"start_character":65,"end_line":44,"end_character":75},"updated":"2016-10-10 01:38:26.000000000","message":"database?","commit_id":"0c34a4fba2ddd2a76e44e1fc8e65cc9e6d7bb5e9"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"3486b6a5870d932b56117597cd736e7c022bce67","unresolved":false,"context_lines":[{"line_number":42,"context_line":"        \"\"\"Updates existing objects and marks obsolete ones for removal."},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"        This is done by reading all the current objects from the repository"},{"line_number":45,"context_line":"        and comparing it with the list we got from the database."},{"line_number":46,"context_line":"        For every object that exists in both, we update it, and for each"},{"line_number":47,"context_line":"        object that was removed from the DB we mark it for removal."},{"line_number":48,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":9,"id":"1a95cdbc_fb8d9dd3","line":45,"range":{"start_line":45,"start_character":55,"end_line":45,"end_character":63},"updated":"2016-10-10 01:38:26.000000000","message":"cache?","commit_id":"0c34a4fba2ddd2a76e44e1fc8e65cc9e6d7bb5e9"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"a8e7fa62811a7578cfd5faae0c893b97a1ea197f","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        self.object_ids_to_remove \u003d set()"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def read(self):"},{"line_number":38,"context_line":"        \"\"\"Reads the objects ids from the database.\"\"\""},{"line_number":39,"context_line":"        self.object_ids_to_remove \u003d set(self.cache_read_ids_callback())"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    def update(self):"}],"source_content_type":"text/x-python","patch_set":10,"id":"1a95cdbc_328b9f20","line":38,"range":{"start_line":38,"start_character":42,"end_line":38,"end_character":50},"updated":"2016-10-10 09:35:29.000000000","message":"This should be cache","commit_id":"885e959d1f1244b6aa8df9994fd098392ccbbbe7"}],"dragonflow/controller/df_local_controller.py":[{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"1ecb5096609682e0ffe535398033f1bfbafeb7e4","unresolved":false,"context_lines":[{"line_number":29,"context_line":"from dragonflow.common import common_params"},{"line_number":30,"context_line":"from dragonflow.common import constants"},{"line_number":31,"context_line":"from dragonflow.common import utils as df_utils"},{"line_number":32,"context_line":"from dragonflow.controller.df_db_objects_refresh import DfObjectRefresher"},{"line_number":33,"context_line":"from dragonflow.controller import ryu_base_app"},{"line_number":34,"context_line":"from dragonflow.controller import topology"},{"line_number":35,"context_line":"from dragonflow.db import api_nb"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_f5716a77","line":32,"updated":"2016-09-26 08:16:49.000000000","message":"Please do not import objects. Import modules, and use the object as df_db_objects_refresher.DfObjectRefresher.","commit_id":"55b751db7989827c0a064724c11dfb21461f2155"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"7f5d674dac37da24a1a3ac5c9ef7f028f82a9773","unresolved":false,"context_lines":[{"line_number":129,"context_line":""},{"line_number":130,"context_line":"            self.register_chassis()"},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"            # TODO(snapiri): Use object refresher for tunnels too?"},{"line_number":133,"context_line":"            self.create_tunnels()"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"            if not self.enable_selective_topo_dist:"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_04230557","line":132,"range":{"start_line":132,"start_character":29,"end_line":132,"end_character":66},"updated":"2016-09-26 08:59:25.000000000","message":"the tunnel and chassis have no data in db_store, and I think there are no problem between them described in your bug:)","commit_id":"55b751db7989827c0a064724c11dfb21461f2155"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"1ecb5096609682e0ffe535398033f1bfbafeb7e4","unresolved":false,"context_lines":[{"line_number":137,"context_line":"                # by the objects dependency in each other"},{"line_number":138,"context_line":"                items \u003d ["},{"line_number":139,"context_line":"                    DfObjectRefresher(\u0027Switches\u0027,"},{"line_number":140,"context_line":"                                      self.db_store.get_lswitch_keys,"},{"line_number":141,"context_line":"                                      self.nb_api.get_all_logical_switches,"},{"line_number":142,"context_line":"                                      self.logical_switch_updated,"},{"line_number":143,"context_line":"                                      self.logical_switch_deleted),"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_15ac168b","line":140,"updated":"2016-09-26 08:16:49.000000000","message":"(See comment in DfObjectRefresher)\nThis method returns keys, but DfObjectRefresher expects objects (maybe pass self.db_store.get_lswitchs?)","commit_id":"55b751db7989827c0a064724c11dfb21461f2155"},{"author":{"_account_id":11343,"name":"Gal Sagie","email":"gal.sagie@gmail.com","username":"GalSagie"},"change_message_id":"64530610f5d4c6dad6b135cc8e6fefdd463fef60","unresolved":false,"context_lines":[{"line_number":143,"context_line":"                        self.nb_api.get_all_logical_switches,"},{"line_number":144,"context_line":"                        self.logical_switch_updated,"},{"line_number":145,"context_line":"                        self.logical_switch_deleted),"},{"line_number":146,"context_line":"                    df_db_objects_refresh.DfObjectRefresher("},{"line_number":147,"context_line":"                        \u0027Security Groups\u0027,"},{"line_number":148,"context_line":"                        self.db_store.get_security_group_keys,"},{"line_number":149,"context_line":"                        self.nb_api.get_security_groups,"}],"source_content_type":"text/x-python","patch_set":9,"id":"1a95cdbc_35c0f64f","line":146,"updated":"2016-10-09 15:43:34.000000000","message":"Security groups should probably be last here (removed first)","commit_id":"0c34a4fba2ddd2a76e44e1fc8e65cc9e6d7bb5e9"},{"author":{"_account_id":11343,"name":"Gal Sagie","email":"gal.sagie@gmail.com","username":"GalSagie"},"change_message_id":"64530610f5d4c6dad6b135cc8e6fefdd463fef60","unresolved":false,"context_lines":[{"line_number":145,"context_line":"                        self.logical_switch_deleted),"},{"line_number":146,"context_line":"                    df_db_objects_refresh.DfObjectRefresher("},{"line_number":147,"context_line":"                        \u0027Security Groups\u0027,"},{"line_number":148,"context_line":"                        self.db_store.get_security_group_keys,"},{"line_number":149,"context_line":"                        self.nb_api.get_security_groups,"},{"line_number":150,"context_line":"                        self.security_group_updated,"},{"line_number":151,"context_line":"                        self.security_group_deleted),"}],"source_content_type":"text/x-python","patch_set":9,"id":"1a95cdbc_95d1ca25","line":148,"updated":"2016-10-09 15:43:34.000000000","message":"could probably do with only get_keys or get_objects for all of these but i guess its just copy of the old functionality so its ok","commit_id":"0c34a4fba2ddd2a76e44e1fc8e65cc9e6d7bb5e9"},{"author":{"_account_id":11343,"name":"Gal Sagie","email":"gal.sagie@gmail.com","username":"GalSagie"},"change_message_id":"64530610f5d4c6dad6b135cc8e6fefdd463fef60","unresolved":false,"context_lines":[{"line_number":155,"context_line":"                        self.nb_api.get_all_logical_ports,"},{"line_number":156,"context_line":"                        self.logical_port_updated,"},{"line_number":157,"context_line":"                        self.logical_port_deleted),"},{"line_number":158,"context_line":"                    df_db_objects_refresh.DfObjectRefresher("},{"line_number":159,"context_line":"                        \u0027Routers\u0027,"},{"line_number":160,"context_line":"                        self.db_store.get_router_keys,"},{"line_number":161,"context_line":"                        self.nb_api.get_routers,"}],"source_content_type":"text/x-python","patch_set":9,"id":"1a95cdbc_55b3c209","line":158,"updated":"2016-10-09 15:43:34.000000000","message":"Not sure if routers should be deleted before ports, this means there is a router port in the DB but no router..\nJust something to consider not sure here.","commit_id":"0c34a4fba2ddd2a76e44e1fc8e65cc9e6d7bb5e9"}],"dragonflow/tests/unit/test_object_refresher.py":[{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"c0cb3cbe925dea3ba3566a4edb36122b7b5054c2","unresolved":false,"context_lines":[{"line_number":56,"context_line":"    def test_db_store(self):"},{"line_number":57,"context_line":"        self.refresher.read()"},{"line_number":58,"context_line":"        self.refresher.update()"},{"line_number":59,"context_line":"        self.refresher.delete()"}],"source_content_type":"text/x-python","patch_set":6,"id":"3a98d1f4_83f5a0cc","line":59,"updated":"2016-09-30 15:54:32.000000000","message":"+1","commit_id":"087f531be9d85b6369310d45923fcabfaa6326e2"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"7adc4d25cd298c1dc48aa3232d8a515e86353170","unresolved":false,"context_lines":[{"line_number":56,"context_line":"    def test_db_store(self):"},{"line_number":57,"context_line":"        self.refresher.read()"},{"line_number":58,"context_line":"        self.refresher.update()"},{"line_number":59,"context_line":"        self.refresher.delete()"}],"source_content_type":"text/x-python","patch_set":6,"id":"3a98d1f4_933ce0e3","line":59,"updated":"2016-09-30 07:11:11.000000000","message":"I am expecting more about the test, for example, the left items in self.test_objs is just the items we want, for example, _cache_update_object is just called with expected times and expected arguments.","commit_id":"087f531be9d85b6369310d45923fcabfaa6326e2"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"3486b6a5870d932b56117597cd736e7c022bce67","unresolved":false,"context_lines":[{"line_number":22,"context_line":"class TestDbObjectsRefresh(tests_base.BaseTestCase):"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    TEST_ITEMS \u003d 8"},{"line_number":25,"context_line":"    ITEMS_TO_DELETE \u003d int(TEST_ITEMS / 2)"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    def setUp(self):"},{"line_number":28,"context_line":"        super(TestDbObjectsRefresh, self).setUp()"}],"source_content_type":"text/x-python","patch_set":9,"id":"1a95cdbc_3b1e2570","line":25,"range":{"start_line":25,"start_character":22,"end_line":25,"end_character":25},"updated":"2016-10-10 01:38:26.000000000","message":"I think the type conversion here is not necessary.","commit_id":"0c34a4fba2ddd2a76e44e1fc8e65cc9e6d7bb5e9"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"3486b6a5870d932b56117597cd736e7c022bce67","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        self.refresher.update()"},{"line_number":62,"context_line":"        self.refresher.delete()"},{"line_number":63,"context_line":"        # Make sure the number of elements is correct"},{"line_number":64,"context_line":"        assert len(self.test_objs) \u003d\u003d self.TEST_ITEMS - self.ITEMS_TO_DELETE"},{"line_number":65,"context_line":"        for item_id in self.deleted_objs:"},{"line_number":66,"context_line":"            # Make sure we do not have the deleted items"},{"line_number":67,"context_line":"            assert item_id not in self.test_objs"}],"source_content_type":"text/x-python","patch_set":9,"id":"1a95cdbc_fb52fd33","line":64,"range":{"start_line":64,"start_character":7,"end_line":64,"end_character":76},"updated":"2016-10-10 01:38:26.000000000","message":"You could try to use self.assertEqual(self.TEST_ITEMS - self.ITEMS_TO_DELETE, len(self.test_objs))","commit_id":"0c34a4fba2ddd2a76e44e1fc8e65cc9e6d7bb5e9"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"3486b6a5870d932b56117597cd736e7c022bce67","unresolved":false,"context_lines":[{"line_number":64,"context_line":"        assert len(self.test_objs) \u003d\u003d self.TEST_ITEMS - self.ITEMS_TO_DELETE"},{"line_number":65,"context_line":"        for item_id in self.deleted_objs:"},{"line_number":66,"context_line":"            # Make sure we do not have the deleted items"},{"line_number":67,"context_line":"            assert item_id not in self.test_objs"}],"source_content_type":"text/x-python","patch_set":9,"id":"1a95cdbc_1b3409fa","line":67,"range":{"start_line":67,"start_character":12,"end_line":67,"end_character":48},"updated":"2016-10-10 01:38:26.000000000","message":"You could try to use self.assertNotIn(item_id, self.test_objs)","commit_id":"0c34a4fba2ddd2a76e44e1fc8e65cc9e6d7bb5e9"}]}
