)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"0104782ed5f30dc0779cbcba025990f18a209212","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch adds DbStore2, based on what we described in NB refactor"},{"line_number":10,"context_line":"spec. It takes into account indexes and is model agnostic (no need to"},{"line_number":11,"context_line":"define new methods for each new model). One we\u0027re done porting all"},{"line_number":12,"context_line":"models from the old code to new, DbStore2 will supercede DbStore and can"},{"line_number":13,"context_line":"be renamed back."},{"line_number":14,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":28,"id":"1a430d35_9b96a04a","line":11,"range":{"start_line":11,"start_character":40,"end_line":11,"end_character":43},"updated":"2017-02-07 02:12:14.000000000","message":"once?","commit_id":"f1b8039a8ce136bcc663dafd0069e4b2448da0af"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"187b190857c222f4581a06ea3c34abcefc72e3fe","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch adds DbStore2, based on what we described in NB refactor"},{"line_number":10,"context_line":"spec. It takes into account indexes and is model agnostic (no need to"},{"line_number":11,"context_line":"define new methods for each new model). One we\u0027re done porting all"},{"line_number":12,"context_line":"models from the old code to new, DbStore2 will supercede DbStore and can"},{"line_number":13,"context_line":"be renamed back."},{"line_number":14,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":28,"id":"fa31d9ce_b2301d03","line":11,"range":{"start_line":11,"start_character":40,"end_line":11,"end_character":43},"in_reply_to":"1a430d35_0fffc5aa","updated":"2017-02-12 09:18:25.000000000","message":"Done","commit_id":"f1b8039a8ce136bcc663dafd0069e4b2448da0af"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"37a8c9840a45a1aa8cb6e58fe2e9438724774bb6","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch adds DbStore2, based on what we described in NB refactor"},{"line_number":10,"context_line":"spec. It takes into account indexes and is model agnostic (no need to"},{"line_number":11,"context_line":"define new methods for each new model). One we\u0027re done porting all"},{"line_number":12,"context_line":"models from the old code to new, DbStore2 will supercede DbStore and can"},{"line_number":13,"context_line":"be renamed back."},{"line_number":14,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":28,"id":"1a430d35_0fffc5aa","line":11,"range":{"start_line":11,"start_character":40,"end_line":11,"end_character":43},"in_reply_to":"1a430d35_9b96a04a","updated":"2017-02-07 07:22:58.000000000","message":"Yes, Thanks, Will update if I respin","commit_id":"f1b8039a8ce136bcc663dafd0069e4b2448da0af"}],"dragonflow/db/db_store2.py":[{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8dc32235418265a4fa2822f716ac577d5b51fce4","unresolved":false,"context_lines":[{"line_number":35,"context_line":"    return tuple(v)"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"def _get_obj_key(obj, fields):"},{"line_number":39,"context_line":"    \"\"\"Extract key for a specific index (tuple of fields)"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"       \u003e\u003e\u003e _get_obj_key(Lport(id\u003d\u00271\u0027, topic\u003d\u00272\u0027, name\u003d\u0027foo\u0027), (\u0027topic\u0027, \u0027id\u0027))"}],"source_content_type":"text/x-python","patch_set":15,"id":"5a3905b3_fb759fca","line":38,"updated":"2017-01-23 17:34:53.000000000","message":"1. the name is misleading. You return the values (plural) of the given fields. Shouldn\u0027t it be _get_obj_values?\n2. nit: Why not return a generator? (and then rename to _iter_obj_values)?","commit_id":"e946ea55fae6e54a99ce638b3f9fbed377c9c986"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8dc32235418265a4fa2822f716ac577d5b51fce4","unresolved":false,"context_lines":[{"line_number":47,"context_line":"class DbStore2(object):"},{"line_number":48,"context_line":"    def __init__(self):"},{"line_number":49,"context_line":"        self._cache \u003d collections.defaultdict("},{"line_number":50,"context_line":"            functools.partial(collections.defaultdict, dict),"},{"line_number":51,"context_line":"        )"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def get(self, obj, index\u003dNone):"}],"source_content_type":"text/x-python","patch_set":15,"id":"5a3905b3_9b3adbe5","line":50,"range":{"start_line":50,"start_character":0,"end_line":50,"end_character":61},"updated":"2017-01-23 17:34:53.000000000","message":"Please move to a variable","commit_id":"e946ea55fae6e54a99ce638b3f9fbed377c9c986"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8dc32235418265a4fa2822f716ac577d5b51fce4","unresolved":false,"context_lines":[{"line_number":54,"context_line":"        \"\"\"Retrieve an object from cache by ID or by a provided index\"\"\""},{"line_number":55,"context_line":"        model \u003d type(obj)"},{"line_number":56,"context_line":"        if index is None:"},{"line_number":57,"context_line":"            index \u003d model.get_indexes().id"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"        fields \u003d _normalize_tuple(index)"},{"line_number":60,"context_line":"        key \u003d _get_obj_key(obj, fields)"}],"source_content_type":"text/x-python","patch_set":15,"id":"5a3905b3_de16114b","line":57,"range":{"start_line":57,"start_character":40,"end_line":57,"end_character":42},"updated":"2017-01-23 17:34:53.000000000","message":"You assume this always exists. Is that the case? Maybe verify upon model construction?","commit_id":"e946ea55fae6e54a99ce638b3f9fbed377c9c986"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8dc32235418265a4fa2822f716ac577d5b51fce4","unresolved":false,"context_lines":[{"line_number":56,"context_line":"        if index is None:"},{"line_number":57,"context_line":"            index \u003d model.get_indexes().id"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"        fields \u003d _normalize_tuple(index)"},{"line_number":60,"context_line":"        key \u003d _get_obj_key(obj, fields)"},{"line_number":61,"context_line":"        return self._cache[model][fields].get(key)"},{"line_number":62,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"5a3905b3_7e7a7d89","line":59,"range":{"start_line":59,"start_character":17,"end_line":59,"end_character":33},"updated":"2017-01-23 17:34:53.000000000","message":"I would prefer indexes to be normalized once upon model construction, if possible.","commit_id":"e946ea55fae6e54a99ce638b3f9fbed377c9c986"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8dc32235418265a4fa2822f716ac577d5b51fce4","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        key \u003d _get_obj_key(obj, fields)"},{"line_number":61,"context_line":"        return self._cache[model][fields].get(key)"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    def get_all(self, model, topic\u003dNone):"},{"line_number":64,"context_line":"        \"\"\"Get all objects of a specific model, or only those with a specific"},{"line_number":65,"context_line":"           topic"},{"line_number":66,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":15,"id":"5a3905b3_1ee7b940","line":63,"updated":"2017-01-23 17:34:53.000000000","message":"No support for indexing/filtering here? (That\u0027s all right, but I want to verify)","commit_id":"e946ea55fae6e54a99ce638b3f9fbed377c9c986"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8dc32235418265a4fa2822f716ac577d5b51fce4","unresolved":false,"context_lines":[{"line_number":73,"context_line":"        # FIXME implement by partial index lookup"},{"line_number":74,"context_line":"        return (v for v in values if v.topic \u003d\u003d topic)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def get_keys(self, model, topic\u003dNone):"},{"line_number":77,"context_line":"        index \u003d _normalize_tuple(model.get_indexes().id_topic)"},{"line_number":78,"context_line":"        values \u003d six.iterkeys(self._cache[model][index])"},{"line_number":79,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"5a3905b3_9e0e49e3","line":76,"updated":"2017-01-23 17:34:53.000000000","message":"docstring missing","commit_id":"e946ea55fae6e54a99ce638b3f9fbed377c9c986"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8dc32235418265a4fa2822f716ac577d5b51fce4","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        return (v for v in values if v.topic \u003d\u003d topic)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def get_keys(self, model, topic\u003dNone):"},{"line_number":77,"context_line":"        index \u003d _normalize_tuple(model.get_indexes().id_topic)"},{"line_number":78,"context_line":"        values \u003d six.iterkeys(self._cache[model][index])"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"        if topic is None:"}],"source_content_type":"text/x-python","patch_set":15,"id":"5a3905b3_1e55f9c4","line":77,"range":{"start_line":77,"start_character":53,"end_line":77,"end_character":61},"updated":"2017-01-23 17:34:53.000000000","message":"Same here: How do you verify this index exists?","commit_id":"e946ea55fae6e54a99ce638b3f9fbed377c9c986"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"42e56bb8ee02ef99a7d678dc76cd4c2e5fd803b6","unresolved":false,"context_lines":[{"line_number":122,"context_line":"_instance_lock \u003d threading.Lock()"},{"line_number":123,"context_line":""},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"def get():"},{"line_number":126,"context_line":"    global _instance"},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"    with _instance_lock:"}],"source_content_type":"text/x-python","patch_set":15,"id":"5a3905b3_b2bc11bc","line":125,"range":{"start_line":125,"start_character":4,"end_line":125,"end_character":8},"updated":"2017-01-23 20:51:34.000000000","message":"Maybe rename to get_instance()?","commit_id":"e946ea55fae6e54a99ce638b3f9fbed377c9c986"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":26,"context_line":"       This index class is responsible for keeping up to date key to object ID"},{"line_number":27,"context_line":"       mapping, and providing ability to query this mapping."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"       Due to the fact that objects themselves are mutable, only store their"},{"line_number":30,"context_line":"       ID. ID to object translation is done by the model cache."},{"line_number":31,"context_line":"    \u0027\u0027\u0027"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    def __init__(self, index):"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_c3f883e8","line":30,"range":{"start_line":29,"start_character":0,"end_line":30,"end_character":63},"updated":"2017-02-04 20:21:51.000000000","message":"Not sure why this is needed? We store a reference to them, so the effect should be similar. If we store object reference rather than ID, it should save us a lookup (and simplify the code). Did I misunderstand something?\n\nIt is also possible that this is needed for the get_keys functionality, but then the comment is misleading.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"a5a56dfaa55f13dec5d26ca7f2f4993b08c17de6","unresolved":false,"context_lines":[{"line_number":26,"context_line":"       This index class is responsible for keeping up to date key to object ID"},{"line_number":27,"context_line":"       mapping, and providing ability to query this mapping."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"       Due to the fact that objects themselves are mutable, only store their"},{"line_number":30,"context_line":"       ID. ID to object translation is done by the model cache."},{"line_number":31,"context_line":"    \u0027\u0027\u0027"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    def __init__(self, index):"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_63feea39","line":30,"range":{"start_line":29,"start_character":0,"end_line":30,"end_character":63},"in_reply_to":"1a430d35_6f36ce04","updated":"2017-02-05 10:43:37.000000000","message":"So basically, you need a hashable object for optimisation, and the ID (being a constant string) is suitable.\n\nMakes sense. But the comment still needs to be updated with this information.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":26,"context_line":"       This index class is responsible for keeping up to date key to object ID"},{"line_number":27,"context_line":"       mapping, and providing ability to query this mapping."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"       Due to the fact that objects themselves are mutable, only store their"},{"line_number":30,"context_line":"       ID. ID to object translation is done by the model cache."},{"line_number":31,"context_line":"    \u0027\u0027\u0027"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    def __init__(self, index):"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_6f36ce04","line":30,"range":{"start_line":29,"start_character":0,"end_line":30,"end_character":63},"in_reply_to":"1a430d35_c3f883e8","updated":"2017-02-05 07:51:41.000000000","message":"get_keys only takes advantage of that. The issue here is that I want to have non-unique keys, like \u0027topic\u0027, and for that I want to a collection at the leaf of the tree we\u0027re holding.\n\nSo its either storing the objects in the collection, or storing the IDs. Now consider and index such as Lport.chassis, we have several buckets that are quite large and there might me some movement of objects between them.\n\nWhat we\u0027ll do is remove the object from one leaf and add to another one. If we\u0027re holding IDs we can store them in a set then remove in O(1) since sets use dictionaries. All objects have string IDs and strings are immutable and hashable so we\u0027re fine as long as we restrict changing ID of stored objects (which we\u0027ll still need to implement, preferably along with staleness).\n\nNow if we store objects themselves we cannot rely on their hash so sets/dicts are useless, we need lists, so while we save an O(1) lookup in model cache later we\u0027re wasting linear time in removal from the bucket.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":72,"context_line":"        return tuple(key)"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"class _ModelCache(object):"},{"line_number":76,"context_line":"    def __init__(self, model):"},{"line_number":77,"context_line":"        self._objs \u003d {}"},{"line_number":78,"context_line":"        self._indexes \u003d {}"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_83a03bf6","line":75,"updated":"2017-02-04 20:21:51.000000000","message":"Docstring missing.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":72,"context_line":"        return tuple(key)"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"class _ModelCache(object):"},{"line_number":76,"context_line":"    def __init__(self, model):"},{"line_number":77,"context_line":"        self._objs \u003d {}"},{"line_number":78,"context_line":"        self._indexes \u003d {}"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_6f688ef6","line":75,"in_reply_to":"1a430d35_83a03bf6","updated":"2017-02-05 07:51:41.000000000","message":"Will add","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":91,"context_line":"        for index in six.itervalues(self._indexes):"},{"line_number":92,"context_line":"            index.delete(obj)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"        self._objs.pop(obj.id)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def update(self, obj):"},{"line_number":97,"context_line":"        for index in six.itervalues(self._indexes):"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_236307de","line":94,"range":{"start_line":94,"start_character":0,"end_line":94,"end_character":30},"updated":"2017-02-04 20:21:51.000000000","message":"nit: Why not del self._objs[obj.id] ?","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":91,"context_line":"        for index in six.itervalues(self._indexes):"},{"line_number":92,"context_line":"            index.delete(obj)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"        self._objs.pop(obj.id)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def update(self, obj):"},{"line_number":97,"context_line":"        for index in six.itervalues(self._indexes):"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_4f63d21a","line":94,"range":{"start_line":94,"start_character":0,"end_line":94,"end_character":30},"in_reply_to":"1a430d35_236307de","updated":"2017-02-05 07:51:41.000000000","message":"No specific reason, will change","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":107,"context_line":"                # Return the first one if there are several matches"},{"line_number":108,"context_line":"                obj_id \u003d next(self.get_all(obj, index))"},{"line_number":109,"context_line":"            except StopIteration:"},{"line_number":110,"context_line":"                raise KeyError()"},{"line_number":111,"context_line":"        try:"},{"line_number":112,"context_line":"            return self._get_by_id(obj_id)"},{"line_number":113,"context_line":"        except KeyError:"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_639b4fca","line":110,"range":{"start_line":110,"start_character":0,"end_line":110,"end_character":32},"updated":"2017-02-04 20:21:51.000000000","message":"I\u0027m not sure I understand - this method returns None when the object isn\u0027t found, or raises KeyError?","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":107,"context_line":"                # Return the first one if there are several matches"},{"line_number":108,"context_line":"                obj_id \u003d next(self.get_all(obj, index))"},{"line_number":109,"context_line":"            except StopIteration:"},{"line_number":110,"context_line":"                raise KeyError()"},{"line_number":111,"context_line":"        try:"},{"line_number":112,"context_line":"            return self._get_by_id(obj_id)"},{"line_number":113,"context_line":"        except KeyError:"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_0fab8a1e","line":110,"range":{"start_line":110,"start_character":0,"end_line":110,"end_character":32},"in_reply_to":"1a430d35_639b4fca","updated":"2017-02-05 07:51:41.000000000","message":"This is a leftover, will fix.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":113,"context_line":"        except KeyError:"},{"line_number":114,"context_line":"            return None"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    def get_keys(self, obj, index):"},{"line_number":117,"context_line":"        # No index, return all keys"},{"line_number":118,"context_line":"        if index is None:"},{"line_number":119,"context_line":"            return six.iterkeys(self._objs)"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_c3aa43d4","line":116,"range":{"start_line":116,"start_character":28,"end_line":116,"end_character":34},"updated":"2017-02-04 20:21:51.000000000","message":"Maybe have a default value?","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"c36dc83635fc80996c20821c5beeb6ecc788e2fd","unresolved":false,"context_lines":[{"line_number":113,"context_line":"        except KeyError:"},{"line_number":114,"context_line":"            return None"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    def get_keys(self, obj, index):"},{"line_number":117,"context_line":"        # No index, return all keys"},{"line_number":118,"context_line":"        if index is None:"},{"line_number":119,"context_line":"            return six.iterkeys(self._objs)"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_29868113","line":116,"range":{"start_line":116,"start_character":28,"end_line":116,"end_character":34},"in_reply_to":"1a430d35_6fc16ee4","updated":"2017-02-05 14:06:39.000000000","message":"Point taken. You can ignore if you wish.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":113,"context_line":"        except KeyError:"},{"line_number":114,"context_line":"            return None"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    def get_keys(self, obj, index):"},{"line_number":117,"context_line":"        # No index, return all keys"},{"line_number":118,"context_line":"        if index is None:"},{"line_number":119,"context_line":"            return six.iterkeys(self._objs)"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_6fc16ee4","line":116,"range":{"start_line":116,"start_character":28,"end_line":116,"end_character":34},"in_reply_to":"1a430d35_c3aa43d4","updated":"2017-02-05 07:51:41.000000000","message":"Why? This is an internal class and this code is only called from DbStore, and always with index param.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":122,"context_line":"        else:"},{"line_number":123,"context_line":"            return self._indexes[index].get_all(obj)"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"    def get_all(self, obj, index):"},{"line_number":126,"context_line":"        ids \u003d self.get_keys(obj, index)"},{"line_number":127,"context_line":"        return (self._get_by_id(id_) for id_ in ids)"},{"line_number":128,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_03ad2be9","line":125,"range":{"start_line":125,"start_character":27,"end_line":125,"end_character":32},"updated":"2017-02-04 20:21:51.000000000","message":"Same here re: default value","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":122,"context_line":"        else:"},{"line_number":123,"context_line":"            return self._indexes[index].get_all(obj)"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"    def get_all(self, obj, index):"},{"line_number":126,"context_line":"        ids \u003d self.get_keys(obj, index)"},{"line_number":127,"context_line":"        return (self._get_by_id(id_) for id_ in ids)"},{"line_number":128,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_8fb69a88","line":125,"range":{"start_line":125,"start_character":27,"end_line":125,"end_character":32},"in_reply_to":"1a430d35_03ad2be9","updated":"2017-02-05 07:51:41.000000000","message":"same","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"c36dc83635fc80996c20821c5beeb6ecc788e2fd","unresolved":false,"context_lines":[{"line_number":122,"context_line":"        else:"},{"line_number":123,"context_line":"            return self._indexes[index].get_all(obj)"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"    def get_all(self, obj, index):"},{"line_number":126,"context_line":"        ids \u003d self.get_keys(obj, index)"},{"line_number":127,"context_line":"        return (self._get_by_id(id_) for id_ in ids)"},{"line_number":128,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_497d8d1b","line":125,"range":{"start_line":125,"start_character":27,"end_line":125,"end_character":32},"in_reply_to":"1a430d35_8fb69a88","updated":"2017-02-05 14:06:39.000000000","message":"Same here.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":132,"context_line":"        self._cache \u003d {}"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":"    def _get_cache(self, model):"},{"line_number":135,"context_line":"        if model not in self._cache:"},{"line_number":136,"context_line":"            self._cache[model] \u003d _ModelCache(model)"},{"line_number":137,"context_line":"        return self._cache[model]"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    def get(self, obj, index\u003dNone):"},{"line_number":140,"context_line":"        \"\"\"Retrieve an object from cache by ID or by a provided index. If"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_63e98f1a","line":137,"range":{"start_line":135,"start_character":0,"end_line":137,"end_character":33},"updated":"2017-02-04 20:21:51.000000000","message":"ni: This version saves a lookup in the positive case, but I am not sure it\u0027s better:\n\ntry:\n    return self._cache[model]\nexcept KeyError:\n    cache \u003d _ModelCache(mode)\n    self._cache[model] \u003d cache\n    return cache","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":132,"context_line":"        self._cache \u003d {}"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":"    def _get_cache(self, model):"},{"line_number":135,"context_line":"        if model not in self._cache:"},{"line_number":136,"context_line":"            self._cache[model] \u003d _ModelCache(model)"},{"line_number":137,"context_line":"        return self._cache[model]"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    def get(self, obj, index\u003dNone):"},{"line_number":140,"context_line":"        \"\"\"Retrieve an object from cache by ID or by a provided index. If"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_6f4fae92","line":137,"range":{"start_line":135,"start_character":0,"end_line":137,"end_character":33},"in_reply_to":"1a430d35_63e98f1a","updated":"2017-02-05 07:51:41.000000000","message":"I don\u0027t mind changing it","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"ac6d856629f684dc6381df7d8868103946945f3b","unresolved":false,"context_lines":[{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    def get(self, obj, index\u003dNone):"},{"line_number":140,"context_line":"        \"\"\"Retrieve an object from cache by ID or by a provided index. If"},{"line_number":141,"context_line":"           several objects match the query, first one is returned"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"           \u003e\u003e\u003e db_store.get(Lport(id\u003d\u0027id1\u0027))"},{"line_number":144,"context_line":"           Lport(...)"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_7d65d5df","line":141,"range":{"start_line":141,"start_character":44,"end_line":141,"end_character":65},"updated":"2017-02-03 09:41:50.000000000","message":"To have a completed meaning of \u0027get\u0027 action, suggest to add several interfaces:\n(1) get_first: return the first one\n(2) get_one: return only one record or throw an exception when multiple records are found\n(3) get: return a list of records\nYou can also remove the get_all function, as it is the same to \u0027get\u0027 function above.\n\nFor example, if you want to get a record according to its ID or other unique key, it is suggested to use get_one.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"901b587a77c21665ad1253d2f92506ea97a8513c","unresolved":false,"context_lines":[{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    def get(self, obj, index\u003dNone):"},{"line_number":140,"context_line":"        \"\"\"Retrieve an object from cache by ID or by a provided index. If"},{"line_number":141,"context_line":"           several objects match the query, first one is returned"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"           \u003e\u003e\u003e db_store.get(Lport(id\u003d\u0027id1\u0027))"},{"line_number":144,"context_line":"           Lport(...)"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_0c0d5390","line":141,"range":{"start_line":141,"start_character":44,"end_line":141,"end_character":65},"in_reply_to":"1a430d35_09838505","updated":"2017-02-05 15:28:34.000000000","message":"Ok, I agree about get_one and get_all (which I prefer to just get). And I agree there is no use for get first at the moment...","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"c36dc83635fc80996c20821c5beeb6ecc788e2fd","unresolved":false,"context_lines":[{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    def get(self, obj, index\u003dNone):"},{"line_number":140,"context_line":"        \"\"\"Retrieve an object from cache by ID or by a provided index. If"},{"line_number":141,"context_line":"           several objects match the query, first one is returned"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"           \u003e\u003e\u003e db_store.get(Lport(id\u003d\u0027id1\u0027))"},{"line_number":144,"context_line":"           Lport(...)"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_09838505","line":141,"range":{"start_line":141,"start_character":44,"end_line":141,"end_character":65},"in_reply_to":"1a430d35_2324e2ad","updated":"2017-02-05 14:06:39.000000000","message":"From a client-code point of view, it\u0027s more readable to use get_one() than get_all()[0].\n\nAnd it verifies the system works as expected - if you have two values, how do you decide which to return in get_one()? In get_first, it\u0027s obvious you want the first one.\n\nIf there are no use-cases for get_first, it may be possible to do without it for now, but the separation between get_all and get_one is important, IMHO.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    def get(self, obj, index\u003dNone):"},{"line_number":140,"context_line":"        \"\"\"Retrieve an object from cache by ID or by a provided index. If"},{"line_number":141,"context_line":"           several objects match the query, first one is returned"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"           \u003e\u003e\u003e db_store.get(Lport(id\u003d\u0027id1\u0027))"},{"line_number":144,"context_line":"           Lport(...)"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_43b73339","line":141,"range":{"start_line":141,"start_character":44,"end_line":141,"end_character":65},"in_reply_to":"1a430d35_7d65d5df","updated":"2017-02-04 20:21:51.000000000","message":"+1","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    def get(self, obj, index\u003dNone):"},{"line_number":140,"context_line":"        \"\"\"Retrieve an object from cache by ID or by a provided index. If"},{"line_number":141,"context_line":"           several objects match the query, first one is returned"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"           \u003e\u003e\u003e db_store.get(Lport(id\u003d\u0027id1\u0027))"},{"line_number":144,"context_line":"           Lport(...)"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_2324e2ad","line":141,"range":{"start_line":141,"start_character":44,"end_line":141,"end_character":65},"in_reply_to":"1a430d35_7d65d5df","updated":"2017-02-05 07:51:41.000000000","message":"I don\u0027t mind changing it, though it might be a bit too specific in my opinion, there\u0027s basically no difference between get_one and get_first. If I know my index is unique, I have no reason to check for extra results like get_one does.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":201,"context_line":"    def __contains__(self, elem):"},{"line_number":202,"context_line":"        return self.get(elem) \u003d\u003d elem"},{"line_number":203,"context_line":""},{"line_number":204,"context_line":"    def get_all_by_topic(self, model, topic\u003dNone):"},{"line_number":205,"context_line":"        return self.get_all("},{"line_number":206,"context_line":"            model(topic\u003dtopic),"},{"line_number":207,"context_line":"            index\u003dmodel.get_indexes()[\u0027topic\u0027],"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_e3dd7f71","line":204,"range":{"start_line":204,"start_character":19,"end_line":204,"end_character":25},"updated":"2017-02-04 20:21:51.000000000","message":"What was decided in the end regarding special functions for the topic index? are they really needed?","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":201,"context_line":"    def __contains__(self, elem):"},{"line_number":202,"context_line":"        return self.get(elem) \u003d\u003d elem"},{"line_number":203,"context_line":""},{"line_number":204,"context_line":"    def get_all_by_topic(self, model, topic\u003dNone):"},{"line_number":205,"context_line":"        return self.get_all("},{"line_number":206,"context_line":"            model(topic\u003dtopic),"},{"line_number":207,"context_line":"            index\u003dmodel.get_indexes()[\u0027topic\u0027],"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_e302da08","line":204,"range":{"start_line":204,"start_character":19,"end_line":204,"end_character":25},"in_reply_to":"1a430d35_e3dd7f71","updated":"2017-02-05 07:51:41.000000000","message":"They are here for convenience, get all by topic is a common case to I though it would be nice to leave it here. I\u0027ll drop if you find this offensive.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"0104782ed5f30dc0779cbcba025990f18a209212","unresolved":false,"context_lines":[{"line_number":44,"context_line":"        self._keys \u003d {}"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    def delete(self, obj):"},{"line_number":47,"context_line":"        key \u003d self._keys.pop(obj.id)"},{"line_number":48,"context_line":"        self._tree.delete(key, obj.id)"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    def update(self, obj):"}],"source_content_type":"text/x-python","patch_set":28,"id":"1a430d35_7b1014a9","line":47,"range":{"start_line":47,"start_character":0,"end_line":47,"end_character":36},"updated":"2017-02-07 02:12:14.000000000","message":"Is it safer to pop(obj.id, None)? to make deletion of a non-exist key pass silently.","commit_id":"f1b8039a8ce136bcc663dafd0069e4b2448da0af"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"512901226dfdb5f4830a14e1a493eae3f041de13","unresolved":false,"context_lines":[{"line_number":44,"context_line":"        self._keys \u003d {}"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    def delete(self, obj):"},{"line_number":47,"context_line":"        key \u003d self._keys.pop(obj.id)"},{"line_number":48,"context_line":"        self._tree.delete(key, obj.id)"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    def update(self, obj):"}],"source_content_type":"text/x-python","patch_set":28,"id":"1a430d35_e3f07169","line":47,"range":{"start_line":47,"start_character":0,"end_line":47,"end_character":36},"in_reply_to":"1a430d35_533a1c9a","updated":"2017-02-09 03:17:52.000000000","message":"Sounds reasonable","commit_id":"f1b8039a8ce136bcc663dafd0069e4b2448da0af"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"37a8c9840a45a1aa8cb6e58fe2e9438724774bb6","unresolved":false,"context_lines":[{"line_number":44,"context_line":"        self._keys \u003d {}"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    def delete(self, obj):"},{"line_number":47,"context_line":"        key \u003d self._keys.pop(obj.id)"},{"line_number":48,"context_line":"        self._tree.delete(key, obj.id)"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    def update(self, obj):"}],"source_content_type":"text/x-python","patch_set":28,"id":"1a430d35_affb11c0","line":47,"range":{"start_line":47,"start_character":0,"end_line":47,"end_character":36},"in_reply_to":"1a430d35_7b1014a9","updated":"2017-02-07 07:22:58.000000000","message":"It would be safer, but I think its best to see first the cases we would need it.\n\nIf we see that it is during a harmless scenario we can turn it silent...","commit_id":"f1b8039a8ce136bcc663dafd0069e4b2448da0af"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"c2712e7c24e9d100f84b762a8988727e789c8e40","unresolved":false,"context_lines":[{"line_number":44,"context_line":"        self._keys \u003d {}"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    def delete(self, obj):"},{"line_number":47,"context_line":"        key \u003d self._keys.pop(obj.id)"},{"line_number":48,"context_line":"        self._tree.delete(key, obj.id)"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    def update(self, obj):"}],"source_content_type":"text/x-python","patch_set":28,"id":"1a430d35_533a1c9a","line":47,"range":{"start_line":47,"start_character":0,"end_line":47,"end_character":36},"in_reply_to":"1a430d35_affb11c0","updated":"2017-02-08 11:12:04.000000000","message":"I\u0027d prefer not to silence potential errors, unless we see they produce false positive bugs. Otherwise, a real bug may be missed.","commit_id":"f1b8039a8ce136bcc663dafd0069e4b2448da0af"}],"dragonflow/tests/unit/test_radix_tree.py":[{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    def test_retrieve_full_index(self):"},{"line_number":29,"context_line":"        rt \u003d radix_tree.RadixTree(2)"},{"line_number":30,"context_line":"        rt.set((1, 2), True)"},{"line_number":31,"context_line":"        rt.set((1, 2), False)"},{"line_number":32,"context_line":"        self.assertItemsEqual({True, False}, rt.get_all((1, 2)))"},{"line_number":33,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_63d0af54","line":30,"range":{"start_line":30,"start_character":23,"end_line":30,"end_character":27},"updated":"2017-02-04 20:21:51.000000000","message":"Why use True and False as values throughout this unit test? Why not strings, so it can be a bit more self-describing?","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    def test_retrieve_full_index(self):"},{"line_number":29,"context_line":"        rt \u003d radix_tree.RadixTree(2)"},{"line_number":30,"context_line":"        rt.set((1, 2), True)"},{"line_number":31,"context_line":"        rt.set((1, 2), False)"},{"line_number":32,"context_line":"        self.assertItemsEqual({True, False}, rt.get_all((1, 2)))"},{"line_number":33,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_433baed1","line":30,"range":{"start_line":30,"start_character":23,"end_line":30,"end_character":27},"in_reply_to":"1a430d35_63d0af54","updated":"2017-02-05 07:51:41.000000000","message":"Will change","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":39,"context_line":"    def test_retrieve_partial_index(self):"},{"line_number":40,"context_line":"        rt \u003d radix_tree.RadixTree(2)"},{"line_number":41,"context_line":"        rt.set((1, 2), True)"},{"line_number":42,"context_line":"        rt.set((1, 3), False)"},{"line_number":43,"context_line":"        self.assertItemsEqual({True, False}, rt.get_all((1, ANY)))"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def test_retrieve_partial_index2(self):"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_43e57335","line":42,"updated":"2017-02-04 20:21:51.000000000","message":"Please add rt.set((2,2), \u003cSomething\u003e), to make sure it isn\u0027t returned.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":39,"context_line":"    def test_retrieve_partial_index(self):"},{"line_number":40,"context_line":"        rt \u003d radix_tree.RadixTree(2)"},{"line_number":41,"context_line":"        rt.set((1, 2), True)"},{"line_number":42,"context_line":"        rt.set((1, 3), False)"},{"line_number":43,"context_line":"        self.assertItemsEqual({True, False}, rt.get_all((1, ANY)))"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def test_retrieve_partial_index2(self):"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_e3501a0d","line":42,"in_reply_to":"1a430d35_43e57335","updated":"2017-02-05 07:51:41.000000000","message":"Will change, though it isn\u0027t returned because we only get 2 items back :)","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"957fb94f750d55c7cb96e808a2472da458433d2e","unresolved":false,"context_lines":[{"line_number":39,"context_line":"    def test_retrieve_partial_index(self):"},{"line_number":40,"context_line":"        rt \u003d radix_tree.RadixTree(2)"},{"line_number":41,"context_line":"        rt.set((1, 2), True)"},{"line_number":42,"context_line":"        rt.set((1, 3), False)"},{"line_number":43,"context_line":"        self.assertItemsEqual({True, False}, rt.get_all((1, ANY)))"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def test_retrieve_partial_index2(self):"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_03a0c642","line":42,"in_reply_to":"1a430d35_e3501a0d","updated":"2017-02-05 10:47:01.000000000","message":"The get_all call should return the same thing with or without rt.set((2,2), ...). I want the test to verify that items that are returned match the query, and that additional items in the RadixTree are not returned..","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":46,"context_line":"        rt \u003d radix_tree.RadixTree(4)"},{"line_number":47,"context_line":"        rt.set((1, 1, 1, 2), True)"},{"line_number":48,"context_line":"        rt.set((1, 2, 3, 2), False)"},{"line_number":49,"context_line":"        rt.set((1, 2, None, 2), False)"},{"line_number":50,"context_line":"        self.assertItemsEqual((True, False, False),"},{"line_number":51,"context_line":"                              rt.get_all((1, ANY, ANY, 2)))"},{"line_number":52,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_83d59b44","line":49,"updated":"2017-02-04 20:21:51.000000000","message":"Same here: add an item that should *not* be returned.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"}],"dragonflow/utils/radix_tree.py":[{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":17,"context_line":"ANY \u003d None"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"class RadixTree(object):"},{"line_number":21,"context_line":"    \u0027\u0027\u0027A constant depth radix tree written (originally) for indexing in DbStore"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    This implementation stores several (or none) items for each path"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_a341b70d","line":20,"range":{"start_line":20,"start_character":6,"end_line":20,"end_character":15},"updated":"2017-02-04 20:21:51.000000000","message":"At some point in the future, this will have to be moved out of Dragonflow.","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":17,"context_line":"ANY \u003d None"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"class RadixTree(object):"},{"line_number":21,"context_line":"    \u0027\u0027\u0027A constant depth radix tree written (originally) for indexing in DbStore"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    This implementation stores several (or none) items for each path"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_235b0230","line":20,"range":{"start_line":20,"start_character":6,"end_line":20,"end_character":15},"in_reply_to":"1a430d35_a341b70d","updated":"2017-02-05 07:51:41.000000000","message":"+1","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"38774bafc7a14aeb9a4d87679b46ebc47b29096d","unresolved":false,"context_lines":[{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        return node"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def get_all(self, path):"},{"line_number":66,"context_line":"        \u0027\u0027\u0027Get all items matching the path provided, if None is present in the"},{"line_number":67,"context_line":"        path, it is treated as a wildcard"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_833cbb94","line":65,"range":{"start_line":65,"start_character":21,"end_line":65,"end_character":27},"updated":"2017-02-04 20:21:51.000000000","message":"Does this assume len(path) \u003d\u003d self._depth?","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"c36dc83635fc80996c20821c5beeb6ecc788e2fd","unresolved":false,"context_lines":[{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        return node"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def get_all(self, path):"},{"line_number":66,"context_line":"        \u0027\u0027\u0027Get all items matching the path provided, if None is present in the"},{"line_number":67,"context_line":"        path, it is treated as a wildcard"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_49a4ada5","line":65,"range":{"start_line":65,"start_character":21,"end_line":65,"end_character":27},"in_reply_to":"1a430d35_0358c631","updated":"2017-02-05 14:06:39.000000000","message":"Then it needs to be documented :)","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9ace314dae299e632e852bfbc0f89a9f2f277d5a","unresolved":false,"context_lines":[{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        return node"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def get_all(self, path):"},{"line_number":66,"context_line":"        \u0027\u0027\u0027Get all items matching the path provided, if None is present in the"},{"line_number":67,"context_line":"        path, it is treated as a wildcard"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"1a430d35_0358c631","line":65,"range":{"start_line":65,"start_character":21,"end_line":65,"end_character":27},"in_reply_to":"1a430d35_833cbb94","updated":"2017-02-05 07:51:41.000000000","message":"Yes","commit_id":"0d237b9f4727b9af5e860633c0eaafe41a5beaed"}]}
