)]}'
{"ironic/sync/zookeeper.py":[{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"54c4fdf242bc9fbf0c0bcbe0d6465d1598287a4e","unresolved":false,"context_lines":[{"line_number":49,"context_line":"_kazoo \u003d None"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"def _get_kazoo_instance():"},{"line_number":53,"context_line":"    global _kazoo"},{"line_number":54,"context_line":"    if not _kazoo:"},{"line_number":55,"context_line":"        _kazoo \u003d client.KazooClient(hosts\u003dCONF.sync.zookeeper_hosts)"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_7dcbeb71","line":52,"updated":"2014-09-12 19:46:27.000000000","message":"This seems sorta ummm, bad.\n\nGlobal state usually isn\u0027t good :-/","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"60a4460d4538c7741998fee02b0e8f2f4fed0bcc","unresolved":false,"context_lines":[{"line_number":49,"context_line":"_kazoo \u003d None"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"def _get_kazoo_instance():"},{"line_number":53,"context_line":"    global _kazoo"},{"line_number":54,"context_line":"    if not _kazoo:"},{"line_number":55,"context_line":"        _kazoo \u003d client.KazooClient(hosts\u003dCONF.sync.zookeeper_hosts)"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_749860c0","line":52,"in_reply_to":"fa98f980_3db88374","updated":"2014-09-13 00:09:37.000000000","message":"Hmmm, I\u0027m unsure about the rest of the ironic codebase, wouldn\u0027t just creating a client in ZooKeeperSyncManager work, or is that per lock? If it is per lock, then I guess this is ok, although seems like a pool object would be better (and the pool object is passed to all ZooKeeperSyncManager objects when they are made).","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":9856,"name":"Kyle Stevenson","email":"kyle@kylestevenson.me","username":"kylestev"},"change_message_id":"99b3d9f2acaac25d49c10b27eb5e2a79ec26cff5","unresolved":false,"context_lines":[{"line_number":49,"context_line":"_kazoo \u003d None"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"def _get_kazoo_instance():"},{"line_number":53,"context_line":"    global _kazoo"},{"line_number":54,"context_line":"    if not _kazoo:"},{"line_number":55,"context_line":"        _kazoo \u003d client.KazooClient(hosts\u003dCONF.sync.zookeeper_hosts)"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_3db88374","line":52,"in_reply_to":"fa98f980_7dcbeb71","updated":"2014-09-12 22:28:21.000000000","message":"Would you suggest that the code create a new Kazoo instance for each lock that needs to be acquired? That seems like quite a bit of unneeded overhead in my opinion.\n\nI understand that global state and singletons aren\u0027t great practice, but I have noticed this pattern being used, and accepted, in other parts of the Ironic codebase.","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"f6f60fc63fdf8ce18cc6195f657347a78156889e","unresolved":false,"context_lines":[{"line_number":72,"context_line":"        return self._zk_path + node_id"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def _acquire(self, node_id):"},{"line_number":75,"context_line":"        path \u003d self._get_node_path(node_id)"},{"line_number":76,"context_line":"        lock \u003d recipe.lock.Lock(self.zk, path, identifier\u003dCONF.host)"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_fd30bb57","line":75,"updated":"2014-09-12 19:55:58.000000000","message":"Just use self.zk.Lock to be consistent here instead of using the recipe class in one place and the client attribute in another...","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":9856,"name":"Kyle Stevenson","email":"kyle@kylestevenson.me","username":"kylestev"},"change_message_id":"99b3d9f2acaac25d49c10b27eb5e2a79ec26cff5","unresolved":false,"context_lines":[{"line_number":72,"context_line":"        return self._zk_path + node_id"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def _acquire(self, node_id):"},{"line_number":75,"context_line":"        path \u003d self._get_node_path(node_id)"},{"line_number":76,"context_line":"        lock \u003d recipe.lock.Lock(self.zk, path, identifier\u003dCONF.host)"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_4eeaeb74","line":75,"in_reply_to":"fa98f980_fd30bb57","updated":"2014-09-12 22:28:21.000000000","message":"That is difficult to test as Kazoo creates a partial function for the Lock recipe which does not behave in an expected manner. I\u0027ll look into it next week.","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"54c4fdf242bc9fbf0c0bcbe0d6465d1598287a4e","unresolved":false,"context_lines":[{"line_number":77,"context_line":""},{"line_number":78,"context_line":"        try:"},{"line_number":79,"context_line":"            lock.acquire()  # TODO(kylestev): do something with this"},{"line_number":80,"context_line":"        except k_exceptions.KazooException:"},{"line_number":81,"context_line":"            data, _ \u003d self.zk.get(path)"},{"line_number":82,"context_line":"            # TODO(kylestev): perhaps log a message here about when the"},{"line_number":83,"context_line":"            # original lock was acquired?"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_9dc6cf66","line":80,"updated":"2014-09-12 19:46:27.000000000","message":"What happens if this get() call fails?","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":9856,"name":"Kyle Stevenson","email":"kyle@kylestevenson.me","username":"kylestev"},"change_message_id":"99b3d9f2acaac25d49c10b27eb5e2a79ec26cff5","unresolved":false,"context_lines":[{"line_number":77,"context_line":""},{"line_number":78,"context_line":"        try:"},{"line_number":79,"context_line":"            lock.acquire()  # TODO(kylestev): do something with this"},{"line_number":80,"context_line":"        except k_exceptions.KazooException:"},{"line_number":81,"context_line":"            data, _ \u003d self.zk.get(path)"},{"line_number":82,"context_line":"            # TODO(kylestev): perhaps log a message here about when the"},{"line_number":83,"context_line":"            # original lock was acquired?"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_3da16346","line":80,"in_reply_to":"fa98f980_9dc6cf66","updated":"2014-09-12 22:28:21.000000000","message":"Good point.","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"00824052eba8a34814332d08c31f818309d378eb","unresolved":false,"context_lines":[{"line_number":89,"context_line":"                self._acquire(node_id)"},{"line_number":90,"context_line":"            except Exception:"},{"line_number":91,"context_line":"                with excutils.save_and_reraise_exception():"},{"line_number":92,"context_line":"                    self.release_node(node_id)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"        return objects.Node.get(context, node_id)"},{"line_number":95,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_bda633a9","line":92,"updated":"2014-09-12 19:51:19.000000000","message":"This doesn\u0027t seem right, the _acquire method can actually have failed to acquire the lock, raised an exception, then this code will catch that and release the lock that someone else owns. That seems bad.","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":9856,"name":"Kyle Stevenson","email":"kyle@kylestevenson.me","username":"kylestev"},"change_message_id":"99b3d9f2acaac25d49c10b27eb5e2a79ec26cff5","unresolved":false,"context_lines":[{"line_number":89,"context_line":"                self._acquire(node_id)"},{"line_number":90,"context_line":"            except Exception:"},{"line_number":91,"context_line":"                with excutils.save_and_reraise_exception():"},{"line_number":92,"context_line":"                    self.release_node(node_id)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"        return objects.Node.get(context, node_id)"},{"line_number":95,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_e0d2ce5a","line":92,"in_reply_to":"fa98f980_bda633a9","updated":"2014-09-12 22:28:21.000000000","message":"Right...","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"495c77575e3e088a9b1b440e2a134a0967de4e4d","unresolved":false,"context_lines":[{"line_number":91,"context_line":"                with excutils.save_and_reraise_exception():"},{"line_number":92,"context_line":"                    self.release_node(node_id)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"        return objects.Node.get(context, node_id)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def release_node(self, node_id, shared\u003dFalse):"},{"line_number":97,"context_line":"        if shared:"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_3d5c037d","line":94,"updated":"2014-09-12 20:03:24.000000000","message":"Something to consider, \n\nWhen u have gotten the lock, and continue to do other work, since this is a distributed system u could lose the lock at any point after u have initially got it, how does this code handle the lose of the lock after it has initially succeeding?\n\nFor example:\n\n 1. Get lock\n 2. Boot baremental\n 3. Do other stuff with baremetal\n 4. Finish\n 5. Do official lock release\n\nAt any point after 1. the lock could be lost (and another owner could claim/acquire it?), either due to disconnection from the zookeeper server, the zookeeper server crashing or other....\n\nJust some things to think about. Distributed systems are hard :-P","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"54c4fdf242bc9fbf0c0bcbe0d6465d1598287a4e","unresolved":false,"context_lines":[{"line_number":100,"context_line":"        node_path \u003d self._get_node_path(node_id)"},{"line_number":101,"context_line":"        if not self.zk.exists(node_path):"},{"line_number":102,"context_line":"            raise exception.NodeNotLocked(node\u003dnode_id)"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"        lock \u003d self.zk.Lock(path\u003dnode_path)"},{"line_number":105,"context_line":"        lock.release()"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_dda3f7af","line":103,"updated":"2014-09-12 19:46:27.000000000","message":"This confuses me.\n\nWhy do this?","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":9856,"name":"Kyle Stevenson","email":"kyle@kylestevenson.me","username":"kylestev"},"change_message_id":"99b3d9f2acaac25d49c10b27eb5e2a79ec26cff5","unresolved":false,"context_lines":[{"line_number":100,"context_line":"        node_path \u003d self._get_node_path(node_id)"},{"line_number":101,"context_line":"        if not self.zk.exists(node_path):"},{"line_number":102,"context_line":"            raise exception.NodeNotLocked(node\u003dnode_id)"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"        lock \u003d self.zk.Lock(path\u003dnode_path)"},{"line_number":105,"context_line":"        lock.release()"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_5d046749","line":103,"in_reply_to":"fa98f980_dda3f7af","updated":"2014-09-12 22:28:21.000000000","message":"This is a WIP for releasing a lock. I\u0027m going to need to find the proper way to release a lock with the same identifier.","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"534c48829174737ae7e7c6e3d318551e0156da41","unresolved":false,"context_lines":[{"line_number":70,"context_line":"                err\u003d\"No value for `node_id` specified\")"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"        return self._zk_path + node_id"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def _acquire(self, tag, node_id):"},{"line_number":75,"context_line":"        path \u003d self._get_node_path(node_id)"},{"line_number":76,"context_line":"        lock \u003d recipe.lock.Lock(self.zk, path, identifier\u003dtag)"}],"source_content_type":"text/x-python","patch_set":7,"id":"fa98f980_f4eb7010","line":73,"updated":"2014-09-13 00:15:15.000000000","message":"Might as well use:\n\nhttps://github.com/python-zk/kazoo/blob/master/kazoo/protocol/paths.py#L19","commit_id":"b53827825f9baf51a2ed4ef2241d822abf63d6dc"},{"author":{"_account_id":9856,"name":"Kyle Stevenson","email":"kyle@kylestevenson.me","username":"kylestev"},"change_message_id":"b9b61d289ffbf9285b4727553b03e7c185c25f0e","unresolved":false,"context_lines":[{"line_number":70,"context_line":"                err\u003d\"No value for `node_id` specified\")"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"        return self._zk_path + node_id"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def _acquire(self, tag, node_id):"},{"line_number":75,"context_line":"        path \u003d self._get_node_path(node_id)"},{"line_number":76,"context_line":"        lock \u003d recipe.lock.Lock(self.zk, path, identifier\u003dtag)"}],"source_content_type":"text/x-python","patch_set":7,"id":"fa98f980_234495b6","line":73,"in_reply_to":"fa98f980_f4eb7010","updated":"2014-09-16 17:33:26.000000000","message":"Nice suggestion!","commit_id":"b53827825f9baf51a2ed4ef2241d822abf63d6dc"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"695ca9df5490310f68df8f7a340cf94a52518617","unresolved":false,"context_lines":[{"line_number":78,"context_line":"        try:"},{"line_number":79,"context_line":"            lock.acquire()  # TODO(kylestev): do something with this"},{"line_number":80,"context_line":"        except k_exceptions.KazooException:"},{"line_number":81,"context_line":"            data, _ \u003d self.zk.get(path)"},{"line_number":82,"context_line":"            # TODO(kylestev): perhaps log a message here about when the"},{"line_number":83,"context_line":"            # original lock was acquired?"},{"line_number":84,"context_line":"            raise exception.NodeLocked(node\u003dnode_id, host\u003ddata.decode(\"utf-8\"))"}],"source_content_type":"text/x-python","patch_set":7,"id":"fa98f980_282ab490","line":81,"updated":"2014-09-16 17:06:53.000000000","message":"Still doesn\u0027t handle the get failing.","commit_id":"b53827825f9baf51a2ed4ef2241d822abf63d6dc"},{"author":{"_account_id":10165,"name":"Marco Morais","email":"mmorais@yahoo-inc.com","username":"mmorais"},"change_message_id":"c40994b74f9d41be1db4b32622f1974da9b4fea4","unresolved":false,"context_lines":[{"line_number":90,"context_line":"            with excutils.save_and_reraise_exception():"},{"line_number":91,"context_line":"                self.release_node(node_id)"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"        return objects.Node.get(context, node_id)"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    def release_node(self, tag, node_id):"},{"line_number":96,"context_line":"        node_path \u003d self._get_node_path(node_id)"}],"source_content_type":"text/x-python","patch_set":7,"id":"fa98f980_0d2d02a9","line":93,"updated":"2014-09-16 18:15:46.000000000","message":"potential race: if you exited self._acquire due to exception, then you access the Node without holding the lock; if you aren\u0027t going to be accessing the protected resource inside of a context block, then you should use the is_acquired member of the lock [1] to determine whether you hold the lock\n\n[1] http://kazoo.readthedocs.org/en/latest/_modules/kazoo/recipe/lock.html#Lock.acquire","commit_id":"b53827825f9baf51a2ed4ef2241d822abf63d6dc"},{"author":{"_account_id":9856,"name":"Kyle Stevenson","email":"kyle@kylestevenson.me","username":"kylestev"},"change_message_id":"3e9521c8738f871df3287a8ccd1a535d9dba5fea","unresolved":false,"context_lines":[{"line_number":90,"context_line":"            with excutils.save_and_reraise_exception():"},{"line_number":91,"context_line":"                self.release_node(node_id)"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"        return objects.Node.get(context, node_id)"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    def release_node(self, tag, node_id):"},{"line_number":96,"context_line":"        node_path \u003d self._get_node_path(node_id)"}],"source_content_type":"text/x-python","patch_set":7,"id":"fa98f980_87cfc656","line":93,"in_reply_to":"fa98f980_0d2d02a9","updated":"2014-09-18 22:35:45.000000000","message":"good catch. thanks for the review!","commit_id":"b53827825f9baf51a2ed4ef2241d822abf63d6dc"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"534c48829174737ae7e7c6e3d318551e0156da41","unresolved":false,"context_lines":[{"line_number":101,"context_line":"        # method can be called on it. This code should not be used."},{"line_number":102,"context_line":"        lock \u003d self.zk.Lock(path\u003dnode_path, identifier\u003dtag)"},{"line_number":103,"context_line":"        # TODO(kylestev): validate the identifier to ensure it matches before"},{"line_number":104,"context_line":"        # it is released"},{"line_number":105,"context_line":"        lock.release()"}],"source_content_type":"text/x-python","patch_set":7,"id":"fa98f980_b4e56839","line":104,"updated":"2014-09-13 00:15:15.000000000","message":"Does this actually work? Looking at the kazoo code it doesn\u0027t appear u can release unless u acquire first.\n\nThe self.node in https://github.com/python-zk/kazoo/blob/master/kazoo/recipe/lock.py#L148 is only created on acquire(), its then used on release() @ https://github.com/python-zk/kazoo/blob/master/kazoo/recipe/lock.py#L225 so this seems like it would croak with a attribute error if that self.node attribute hasn\u0027t been created/set.","commit_id":"b53827825f9baf51a2ed4ef2241d822abf63d6dc"},{"author":{"_account_id":9856,"name":"Kyle Stevenson","email":"kyle@kylestevenson.me","username":"kylestev"},"change_message_id":"3e9521c8738f871df3287a8ccd1a535d9dba5fea","unresolved":false,"context_lines":[{"line_number":101,"context_line":"        # method can be called on it. This code should not be used."},{"line_number":102,"context_line":"        lock \u003d self.zk.Lock(path\u003dnode_path, identifier\u003dtag)"},{"line_number":103,"context_line":"        # TODO(kylestev): validate the identifier to ensure it matches before"},{"line_number":104,"context_line":"        # it is released"},{"line_number":105,"context_line":"        lock.release()"}],"source_content_type":"text/x-python","patch_set":7,"id":"fa98f980_d2d98e23","line":104,"in_reply_to":"fa98f980_634dbd99","updated":"2014-09-18 22:35:45.000000000","message":"I don\u0027t think having a single lock instance is acceptable. There does need to be some more thought put into how releasing will work -- not 100% sure what the final implementation will be at this point.","commit_id":"b53827825f9baf51a2ed4ef2241d822abf63d6dc"},{"author":{"_account_id":9856,"name":"Kyle Stevenson","email":"kyle@kylestevenson.me","username":"kylestev"},"change_message_id":"b9b61d289ffbf9285b4727553b03e7c185c25f0e","unresolved":false,"context_lines":[{"line_number":101,"context_line":"        # method can be called on it. This code should not be used."},{"line_number":102,"context_line":"        lock \u003d self.zk.Lock(path\u003dnode_path, identifier\u003dtag)"},{"line_number":103,"context_line":"        # TODO(kylestev): validate the identifier to ensure it matches before"},{"line_number":104,"context_line":"        # it is released"},{"line_number":105,"context_line":"        lock.release()"}],"source_content_type":"text/x-python","patch_set":7,"id":"fa98f980_83e621af","line":104,"in_reply_to":"fa98f980_b4e56839","updated":"2014-09-16 17:33:26.000000000","message":"Yep, I\u0027ll get around to fixing it. I did make a comment stating it shouldn\u0027t be used. This is a WIP after all ;)","commit_id":"b53827825f9baf51a2ed4ef2241d822abf63d6dc"},{"author":{"_account_id":10165,"name":"Marco Morais","email":"mmorais@yahoo-inc.com","username":"mmorais"},"change_message_id":"c40994b74f9d41be1db4b32622f1974da9b4fea4","unresolved":false,"context_lines":[{"line_number":101,"context_line":"        # method can be called on it. This code should not be used."},{"line_number":102,"context_line":"        lock \u003d self.zk.Lock(path\u003dnode_path, identifier\u003dtag)"},{"line_number":103,"context_line":"        # TODO(kylestev): validate the identifier to ensure it matches before"},{"line_number":104,"context_line":"        # it is released"},{"line_number":105,"context_line":"        lock.release()"}],"source_content_type":"text/x-python","patch_set":7,"id":"fa98f980_634dbd99","line":104,"in_reply_to":"fa98f980_b4e56839","updated":"2014-09-16 18:15:46.000000000","message":"not sure, but what might help fix the semantics is to have just a single lock instance as a member of ZooKeeperSyncManager; a release of a lock that you don\u0027t own is ok [1], the function will just return false\n\n[1] http://kazoo.readthedocs.org/en/latest/_modules/kazoo/recipe/lock.html#Lock.release","commit_id":"b53827825f9baf51a2ed4ef2241d822abf63d6dc"}],"ironic/tests/sync/test_sync_zookeeper.py":[{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"1f8375b8ebb789ae1bef33b96cfe1665275a5033","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        super(ZooKeeperSyncManagerTestCase, self).setUp()"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"        # mock the get instance method so we don\u0027t actually try to connect to"},{"line_number":35,"context_line":"        # a ZooKeeper server"},{"line_number":36,"context_line":"        zookeeper._get_kazoo_instance \u003d mock.Mock(return_value\u003dmock.Mock())"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"        self.host \u003d \u0027test-host\u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_7dce8b5b","line":35,"updated":"2014-09-12 19:53:41.000000000","message":"For this whole thing I\u0027d recommend using something else.\n\nhttps://pypi.python.org/pypi/zake\n\nI created the above to allow u to have a in-memory zookeeper client that acts like a real zookeeper client, and that zake client can be introspected during, after tests and so on.\n\nIt\u0027d probably be better to just use zake instead of all these mocks and so on... Then u are testing actual functionality, instead of mocks...","commit_id":"d9975af0d0a45aad0c56598fdc9ddc458ba8f264"}]}
