)]}'
{"taskflow/persistence/backends/impl_memory.py":[{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"6199d8d3d23038ab0b040e683d8cf1276126aa12","unresolved":false,"context_lines":[{"line_number":15,"context_line":"#    License for the specific language governing permissions and limitations"},{"line_number":16,"context_line":"#    under the License."},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from contextlib import contextmanager"},{"line_number":19,"context_line":"from copy import deepcopy"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from taskflow import exceptions as exc"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba7be1f8_a1da9b48","line":18,"updated":"2015-03-03 20:00:35.000000000","message":"So these 2 will likely break flake8/pep8 since they don\u0027t like importing functions, just import the module, then use the function from it.\n\nSo usage becomes copy.deepcopy instead of deepcopy.\n\nhttp://docs.openstack.org/developer/hacking/#imports","commit_id":"31060a98cd26f445e666fb52ac946fee0f3064fc"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"6199d8d3d23038ab0b040e683d8cf1276126aa12","unresolved":false,"context_lines":[{"line_number":81,"context_line":"            except Exception as e:"},{"line_number":82,"context_line":"                raise exc.StorageFailure(\"Storage backend internal error\", e)"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"    def _follow_path(self, path):"},{"line_number":85,"context_line":"        node \u003d self.backend.memory"},{"line_number":86,"context_line":"        for part in path:"},{"line_number":87,"context_line":"            node \u003d node.children[part]"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba7be1f8_a13e1b89","line":84,"updated":"2015-03-03 20:00:35.000000000","message":"So interesting question/idea.\n\nWould using a http://docs.openstack.org/developer/taskflow/types.html#module-taskflow.types.tree work here? It seems like this is a tree-like structure? Might as well eat our own dogfood, if we can.","commit_id":"31060a98cd26f445e666fb52ac946fee0f3064fc"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"d4596dc81c6fa2e38e0223cf536700c575e57acf","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    def __init__(self, conf\u003dNone):"},{"line_number":38,"context_line":"        if conf is None:"},{"line_number":39,"context_line":"            conf \u003d {}"},{"line_number":40,"context_line":"        if \"path\" not in conf:"},{"line_number":41,"context_line":"            conf[\"path\"] \u003d \"/\""},{"line_number":42,"context_line":"        super(MemoryBackend, self).__init__(conf)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_e549918c","line":39,"updated":"2015-03-04 23:29:25.000000000","message":"Should we even care about a path in conf or setting one, since it doesn\u0027t seem like we use it anyway (since ``Node(\"/\")`` is always created with \"/\")..","commit_id":"9a0aab69922669798646f7e019317a34e92d6c72"},{"author":{"_account_id":11024,"name":"Dan Krause","email":"dan@dankrause.net","username":"dankrause"},"change_message_id":"c3016d9ba087da2b4d3929e42c0502403e27e2d4","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    def __init__(self, conf\u003dNone):"},{"line_number":38,"context_line":"        if conf is None:"},{"line_number":39,"context_line":"            conf \u003d {}"},{"line_number":40,"context_line":"        if \"path\" not in conf:"},{"line_number":41,"context_line":"            conf[\"path\"] \u003d \"/\""},{"line_number":42,"context_line":"        super(MemoryBackend, self).__init__(conf)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_8710b4a9","line":39,"in_reply_to":"9a80dd14_676f40c6","updated":"2015-03-05 15:06:41.000000000","message":"Ahh, actually, backend.path is used to build book_path, flow_path, and atom_path in the base class. I can\u0027t tear it out. I\u0027ll set the root node using the conf value, though it won\u0027t be particularly useful for a user to change.","commit_id":"9a0aab69922669798646f7e019317a34e92d6c72"},{"author":{"_account_id":11024,"name":"Dan Krause","email":"dan@dankrause.net","username":"dankrause"},"change_message_id":"2d89146cf7d35c864473ea1542389554fb443eb0","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    def __init__(self, conf\u003dNone):"},{"line_number":38,"context_line":"        if conf is None:"},{"line_number":39,"context_line":"            conf \u003d {}"},{"line_number":40,"context_line":"        if \"path\" not in conf:"},{"line_number":41,"context_line":"            conf[\"path\"] \u003d \"/\""},{"line_number":42,"context_line":"        super(MemoryBackend, self).__init__(conf)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_676f40c6","line":39,"in_reply_to":"9a80dd14_e549918c","updated":"2015-03-05 15:03:32.000000000","message":"The base class requires a path to be set. I can move that to the other two sub-classes if you prefer.","commit_id":"9a0aab69922669798646f7e019317a34e92d6c72"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"d4596dc81c6fa2e38e0223cf536700c575e57acf","unresolved":false,"context_lines":[{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    def _ensure_path(self, path):"},{"line_number":107,"context_line":"        with self._memory_lock(write\u003dTrue):"},{"line_number":108,"context_line":"            path \u003d os.path.normpath(path)"},{"line_number":109,"context_line":"            parts \u003d path.split(os.sep)"},{"line_number":110,"context_line":"            node \u003d self.backend.memory"},{"line_number":111,"context_line":"            for p in range(len(parts) - 1):"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_e057bf00","line":108,"updated":"2015-03-04 23:29:25.000000000","message":"So I\u0027m wondering if we should avoid using os.path functions and just use a mini-set of our own (that always ensures / is used), I believe this will start to do things on windows that may not be desired (for example, apparently it converts backslashes to forward slashes). I\u0027m not saying that people are using windows + taskflow but it doesn\u0027t seem like we should make that impossible/invalid.\n\nhttps://docs.python.org/2/library/os.path.html#os.path.normpath\n\nMaybe have our own miniature normpath, split, join (that always ensure \"/\" is used); this is similar to what kazoo does also (although we should probably avoid just using there code: https://github.com/python-zk/kazoo/blob/master/kazoo/protocol/paths.py ; since we tightly control the path values it seems like we should be able to make some small split, join, (do we need a normpath then?) functions that are really simple and just use them?\n\nWhat do u think?","commit_id":"9a0aab69922669798646f7e019317a34e92d6c72"},{"author":{"_account_id":11024,"name":"Dan Krause","email":"dan@dankrause.net","username":"dankrause"},"change_message_id":"2d89146cf7d35c864473ea1542389554fb443eb0","unresolved":false,"context_lines":[{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    def _ensure_path(self, path):"},{"line_number":107,"context_line":"        with self._memory_lock(write\u003dTrue):"},{"line_number":108,"context_line":"            path \u003d os.path.normpath(path)"},{"line_number":109,"context_line":"            parts \u003d path.split(os.sep)"},{"line_number":110,"context_line":"            node \u003d self.backend.memory"},{"line_number":111,"context_line":"            for p in range(len(parts) - 1):"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_c7770c3a","line":108,"in_reply_to":"9a80dd14_e057bf00","updated":"2015-03-05 15:03:32.000000000","message":"So aside from the root node in the tree (which I didn\u0027t think about, and will fix) I\u0027m using os path functions and os.sep for everything. Assuming I use Node(os.sep) for the root node, everything will just use os-specific path handling. Paths here are opaque to the user of impl_memory, assuming _join_path is properly used everywhere.","commit_id":"9a0aab69922669798646f7e019317a34e92d6c72"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"ef128a7d9ae581e382cd1d73b2e8d26eb0ee68ce","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    writing and reading by using a read/write locks."},{"line_number":37,"context_line":"    \"\"\""},{"line_number":38,"context_line":"    def __init__(self, conf\u003dNone):"},{"line_number":39,"context_line":"        if conf is None:"},{"line_number":40,"context_line":"            conf \u003d {}"},{"line_number":41,"context_line":"        if \"path\" not in conf:"},{"line_number":42,"context_line":"            conf[\"path\"] \u003d os.sep"}],"source_content_type":"text/x-python","patch_set":9,"id":"9a80dd14_05e9c0e5","line":39,"updated":"2015-03-07 23:47:22.000000000","message":"Just out of curosity why is this done; the base class checks for conf being none and then sets it to a empty dictionary. Why not just let it do that and then after the base class finished u can adjust the self._conf variable and do do whatever u want. Is there any reason to do it before calling into the parent class (some kind of python thing that I don\u0027t know about?)","commit_id":"09fca0b4ceddb6488529e31f0695eeb0a83b26fe"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"06ae0818d5ecceb857a6016e4aa846246add36fe","unresolved":false,"context_lines":[{"line_number":37,"context_line":"    \"\"\""},{"line_number":38,"context_line":"    def __init__(self, conf\u003dNone):"},{"line_number":39,"context_line":"        super(MemoryBackend, self).__init__(conf)"},{"line_number":40,"context_line":"        if \"path\" not in conf or conf[\"path\"] is None:"},{"line_number":41,"context_line":"            conf[\"path\"] \u003d os.sep"},{"line_number":42,"context_line":"        self.memory \u003d Node(self._conf[\"path\"])"},{"line_number":43,"context_line":"        self.lock \u003d lock_utils.ReaderWriterLock()"}],"source_content_type":"text/x-python","patch_set":12,"id":"9a80dd14_c5e304d7","line":40,"updated":"2015-03-09 17:57:09.000000000","message":"Should these all be self._conf (so that the none case is handled, since the parent class sets it to an empty dictionary when none/falsey...)?","commit_id":"1a0900ff79e65a437a4f1fbe34aed16f10efdba0"}],"taskflow/persistence/backends/impl_zookeeper.py":[{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"9267671ae4ebfcc0276dd580316149cdb628ecfd","unresolved":false,"context_lines":[{"line_number":32,"context_line":""},{"line_number":33,"context_line":"class ZkBackend(path_based.PathBasedBackend):"},{"line_number":34,"context_line":"    \"\"\"A zookeeper-backed backend."},{"line_number":35,"context_line":"    Example configuration::"},{"line_number":36,"context_line":"    #    conf \u003d {"},{"line_number":37,"context_line":"    #        \"hosts\": \"192.168.0.1:2181,192.168.0.2:2181,192.168.0.3:2181\","},{"line_number":38,"context_line":"    #        \"path\": \"/taskflow\","}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_30c1972f","line":35,"updated":"2015-03-03 18:58:56.000000000","message":"Hey where the comment go :-P","commit_id":"9394a9de109ed9d6e62cd6fe087922ec2d658991"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"6199d8d3d23038ab0b040e683d8cf1276126aa12","unresolved":false,"context_lines":[{"line_number":32,"context_line":""},{"line_number":33,"context_line":"class ZkBackend(path_based.PathBasedBackend):"},{"line_number":34,"context_line":"    \"\"\"A zookeeper-backed backend."},{"line_number":35,"context_line":"    Example configuration::"},{"line_number":36,"context_line":"    #    conf \u003d {"},{"line_number":37,"context_line":"    #        \"hosts\": \"192.168.0.1:2181,192.168.0.2:2181,192.168.0.3:2181\","},{"line_number":38,"context_line":"    #        \"path\": \"/taskflow\","}],"source_content_type":"text/x-python","patch_set":2,"id":"ba7be1f8_41c2bf53","line":35,"updated":"2015-03-03 20:00:35.000000000","message":"Should we uncomment the example config that u commented?","commit_id":"31060a98cd26f445e666fb52ac946fee0f3064fc"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"b244b241f42c92b8714b1f5f0d24dcffe1c16b0d","unresolved":false,"context_lines":[{"line_number":139,"context_line":"        transaction \u003d self._client.transaction()"},{"line_number":140,"context_line":"        with self._exc_wrapper():"},{"line_number":141,"context_line":"            yield transaction"},{"line_number":142,"context_line":"        k_utils.checked_commit(transaction)"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"    def validate(self):"},{"line_number":145,"context_line":"        with self._exc_wrapper():"}],"source_content_type":"text/x-python","patch_set":8,"id":"9a80dd14_dc006d36","line":142,"updated":"2015-03-06 23:27:38.000000000","message":"I think u want this under the with self._exc_wrapper(): so that if the commit fails the error gets converted correctly right?","commit_id":"251378a8bc33b51872a67b5440345c3d35ffa048"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"0d3703c104caa1776225bec685dca684a1df9fad","unresolved":false,"context_lines":[{"line_number":41,"context_line":"    \"\"\""},{"line_number":42,"context_line":"    def __init__(self, conf, client\u003dNone):"},{"line_number":43,"context_line":"        super(ZkBackend, self).__init__(conf)"},{"line_number":44,"context_line":"        path \u003d str(conf.get(\"path\", \"/taskflow\"))"},{"line_number":45,"context_line":"        if not path:"},{"line_number":46,"context_line":"            raise ValueError(\"Empty zookeeper path is disallowed\")"},{"line_number":47,"context_line":"        if not paths.isabs(path):"}],"source_content_type":"text/x-python","patch_set":12,"id":"9a80dd14_851aecc3","line":44,"updated":"2015-03-09 18:00:08.000000000","message":"Hmmm, I wonder if this should use self._conf also.","commit_id":"1a0900ff79e65a437a4f1fbe34aed16f10efdba0"}],"taskflow/persistence/path_based.py":[{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"9267671ae4ebfcc0276dd580316149cdb628ecfd","unresolved":false,"context_lines":[{"line_number":21,"context_line":"from taskflow.persistence import base, logbook"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"def _serialize(obj):"},{"line_number":25,"context_line":"        if isinstance(obj, logbook.LogBook):"},{"line_number":26,"context_line":"            return obj.to_dict(marshal_time\u003dTrue)"},{"line_number":27,"context_line":"        elif isinstance(obj, logbook.FlowDetail):"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_2da78451","line":24,"updated":"2015-03-03 18:58:56.000000000","message":"4 spaces not 8?","commit_id":"9394a9de109ed9d6e62cd6fe087922ec2d658991"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"9267671ae4ebfcc0276dd580316149cdb628ecfd","unresolved":false,"context_lines":[{"line_number":30,"context_line":"            return base._format_atom(obj)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"def _deserialize(cls, data):"},{"line_number":34,"context_line":"    if issubclass(cls, logbook.LogBook):"},{"line_number":35,"context_line":"        return cls.from_dict(data, unmarshal_time\u003dTrue)"},{"line_number":36,"context_line":"    elif issubclass(cls, logbook.FlowDetail):"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_50b36b4c","line":33,"updated":"2015-03-03 18:58:56.000000000","message":"What about making both of these classmethod/staticmethods in the class itself, so that if a class really wants to override this, it can. What do u think?","commit_id":"9394a9de109ed9d6e62cd6fe087922ec2d658991"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"9267671ae4ebfcc0276dd580316149cdb628ecfd","unresolved":false,"context_lines":[{"line_number":115,"context_line":"    def _transaction(self):"},{"line_number":116,"context_line":"        \"\"\"Context manager that yields a transaction\"\"\""},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"    def _get_obj_path(self, obj):"},{"line_number":119,"context_line":"            if isinstance(obj, logbook.LogBook):"},{"line_number":120,"context_line":"                path \u003d self.book_path"},{"line_number":121,"context_line":"            elif isinstance(obj, logbook.FlowDetail):"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_cd6fc8fa","line":118,"updated":"2015-03-03 18:58:56.000000000","message":"4 spaces?\n\nAlso what do u think about using the following to do the matching?\n\nhttps://github.com/openstack/taskflow/blob/master/taskflow/utils/misc.py#L90","commit_id":"9394a9de109ed9d6e62cd6fe087922ec2d658991"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"9267671ae4ebfcc0276dd580316149cdb628ecfd","unresolved":false,"context_lines":[{"line_number":175,"context_line":"                flow_details.add(atom_details)"},{"line_number":176,"context_line":"        return flow_details"},{"line_number":177,"context_line":""},{"line_number":178,"context_line":"    def update_flow_details(self, flow_detail, transaction\u003dNone,"},{"line_number":179,"context_line":"                            ignore_missing\u003dFalse):"},{"line_number":180,"context_line":"        def do_update(flow_detail, transaction):"},{"line_number":181,"context_line":"            flow_path \u003d self._get_obj_path(flow_detail)"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_30eef7ed","line":178,"updated":"2015-03-03 18:58:56.000000000","message":"So this one feels sorta weird to me, having the ability for users to pass in a transaction (as part of the public api); is there anyway we can avoid that (or have a _update_flow_details that takes a transcation and is used internally, while the update_flow_details doesn\u0027t take a transcation)?","commit_id":"9394a9de109ed9d6e62cd6fe087922ec2d658991"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"9267671ae4ebfcc0276dd580316149cdb628ecfd","unresolved":false,"context_lines":[{"line_number":204,"context_line":"        atom_data \u003d self._get_item(atom_path)"},{"line_number":205,"context_line":"        return _deserialize(logbook.AtomDetail, atom_data)"},{"line_number":206,"context_line":""},{"line_number":207,"context_line":"    def update_atom_details(self, atom_detail, transaction\u003dNone,"},{"line_number":208,"context_line":"                            ignore_missing\u003dFalse):"},{"line_number":209,"context_line":"        if transaction is not None:"},{"line_number":210,"context_line":"            return self._update_object(atom_detail, transaction,"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_d0b67bf8","line":207,"updated":"2015-03-03 18:58:56.000000000","message":"Same oddness about having transcation be part of the public api.","commit_id":"9394a9de109ed9d6e62cd6fe087922ec2d658991"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"9267671ae4ebfcc0276dd580316149cdb628ecfd","unresolved":false,"context_lines":[{"line_number":215,"context_line":"                                           ignore_missing)"},{"line_number":216,"context_line":""},{"line_number":217,"context_line":"    def destroy_logbook(self, book_uuid, transaction\u003dNone):"},{"line_number":218,"context_line":"        book_path \u003d self._join_path(self.book_path, book_uuid)"},{"line_number":219,"context_line":""},{"line_number":220,"context_line":"        def do_destroy(book_uuid, transaction):"},{"line_number":221,"context_line":"            for flow_uuid in self._get_children(book_path):"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_f0a37f9b","line":218,"updated":"2015-03-03 18:58:56.000000000","message":"Same oddness about having transcation be part of the public api.","commit_id":"9394a9de109ed9d6e62cd6fe087922ec2d658991"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"ef128a7d9ae581e382cd1d73b2e8d26eb0ee68ce","unresolved":false,"context_lines":[{"line_number":35,"context_line":"    \"\"\""},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def __init__(self, conf):"},{"line_number":38,"context_line":"        self._path \u003d conf.get(\u0027path\u0027, None)"},{"line_number":39,"context_line":"        super(PathBasedBackend, self).__init__(conf)"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":9,"id":"9a80dd14_65ec3cf4","line":38,"updated":"2015-03-07 23:47:22.000000000","message":"Same kind of question to the other one, why do this before calling into the parent instead of after?","commit_id":"09fca0b4ceddb6488529e31f0695eeb0a83b26fe"}]}
