)]}'
{"tempest/cmd/init.py":[{"author":{"_account_id":6167,"name":"Ken\u0027ichi Ohmichi","email":"ken1ohmichi@gmail.com","username":"oomichi"},"change_message_id":"cb676d304d0674c9dd0b167fec213cc10f597a73","unresolved":false,"context_lines":[{"line_number":93,"context_line":"                                 \"then exit\")"},{"line_number":94,"context_line":"        parser.add_argument(\u0027--name\u0027, help\u003d\"The workspace name\","},{"line_number":95,"context_line":"                            default\u003dos.getcwd().split(os.path.sep)[-1])"},{"line_number":96,"context_line":"        parser.add_argument(\u0027--workspace-path\u0027, default\u003dNone)"},{"line_number":97,"context_line":"        return parser"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"    def generate_testr_conf(self, local_path):"}],"source_content_type":"text/x-python","patch_set":12,"id":"dab17558_ee097b32","line":96,"range":{"start_line":96,"start_character":28,"end_line":96,"end_character":46},"updated":"2016-05-17 07:33:39.000000000","message":"Can we add any help about this option?","commit_id":"0dc3aef6caa4f1482a79ec76bdbe6fbbcf8766cd"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"c44f7bafa4c459c4897d65be933a23b5b6ef1006","unresolved":false,"context_lines":[{"line_number":93,"context_line":"                                 \"then exit\")"},{"line_number":94,"context_line":"        parser.add_argument(\u0027--name\u0027, help\u003d\"The workspace name\","},{"line_number":95,"context_line":"                            default\u003dos.getcwd().split(os.path.sep)[-1])"},{"line_number":96,"context_line":"        parser.add_argument(\u0027--workspace-path\u0027, default\u003dNone)"},{"line_number":97,"context_line":"        return parser"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"    def generate_testr_conf(self, local_path):"}],"source_content_type":"text/x-python","patch_set":12,"id":"dab17558_a4d3f802","line":96,"range":{"start_line":96,"start_character":28,"end_line":96,"end_character":46},"in_reply_to":"dab17558_ee097b32","updated":"2016-05-17 15:06:28.000000000","message":"Done","commit_id":"0dc3aef6caa4f1482a79ec76bdbe6fbbcf8766cd"}],"tempest/cmd/workspace.py":[{"author":{"_account_id":9152,"name":"Castulo J. Martinez","email":"castulo.martinez@intel.com","username":"cas"},"change_message_id":"25fd13f51db0afc4855b41b6973a9e87f9245545","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            if workspace.get(key) \u003d\u003d old:"},{"line_number":43,"context_line":"                workspace.update({key: new})"},{"line_number":44,"context_line":"                break"},{"line_number":45,"context_line":"        self._write_file()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def register_new_workspace(self, name, path, init\u003dFalse):"},{"line_number":48,"context_line":"        \"\"\"Adds the new workspace and writes out the new workspace config\"\"\""}],"source_content_type":"text/x-python","patch_set":9,"id":"1af94dfe_32249ac3","line":45,"range":{"start_line":45,"start_character":8,"end_line":45,"end_character":26},"updated":"2016-03-17 21:41:10.000000000","message":"This party could also use a path validation","commit_id":"9c268311ce6262553f81cac383cd2016328f5585"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"a0639f9805e8d039715d5b64f7fe91c68ac1dc02","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            if workspace.get(key) \u003d\u003d old:"},{"line_number":43,"context_line":"                workspace.update({key: new})"},{"line_number":44,"context_line":"                break"},{"line_number":45,"context_line":"        self._write_file()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def register_new_workspace(self, name, path, init\u003dFalse):"},{"line_number":48,"context_line":"        \"\"\"Adds the new workspace and writes out the new workspace config\"\"\""}],"source_content_type":"text/x-python","patch_set":9,"id":"fa0719c6_b613015c","line":45,"range":{"start_line":45,"start_character":8,"end_line":45,"end_character":26},"in_reply_to":"1af94dfe_32249ac3","updated":"2016-03-21 16:22:12.000000000","message":"Are you asking to run _validate_workspaces before the write?\n\nAs per the spec, the validation / removal of dead workspaces only happens during the list command.","commit_id":"9c268311ce6262553f81cac383cd2016328f5585"},{"author":{"_account_id":9152,"name":"Castulo J. Martinez","email":"castulo.martinez@intel.com","username":"cas"},"change_message_id":"25fd13f51db0afc4855b41b6973a9e87f9245545","unresolved":false,"context_lines":[{"line_number":52,"context_line":"                    name))"},{"line_number":53,"context_line":"                exit(1)"},{"line_number":54,"context_line":"        self.workspaces.append({\"name\": name, \"path\": path})"},{"line_number":55,"context_line":"        self._write_file()"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    def _validate_workspaces(self):"},{"line_number":58,"context_line":"        for workspace in self.workspaces:"}],"source_content_type":"text/x-python","patch_set":9,"id":"1af94dfe_b250aa33","line":55,"range":{"start_line":55,"start_character":8,"end_line":55,"end_character":26},"updated":"2016-03-17 21:41:10.000000000","message":"Here is where I think it would be good to validate the workspace path","commit_id":"9c268311ce6262553f81cac383cd2016328f5585"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"a0639f9805e8d039715d5b64f7fe91c68ac1dc02","unresolved":false,"context_lines":[{"line_number":52,"context_line":"                    name))"},{"line_number":53,"context_line":"                exit(1)"},{"line_number":54,"context_line":"        self.workspaces.append({\"name\": name, \"path\": path})"},{"line_number":55,"context_line":"        self._write_file()"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    def _validate_workspaces(self):"},{"line_number":58,"context_line":"        for workspace in self.workspaces:"}],"source_content_type":"text/x-python","patch_set":9,"id":"fa0719c6_f64bb957","line":55,"range":{"start_line":55,"start_character":8,"end_line":55,"end_character":26},"in_reply_to":"1af94dfe_b250aa33","updated":"2016-03-21 16:22:12.000000000","message":"I\u0027ll add a _validate_workspaces if it\u0027s not created via init.","commit_id":"9c268311ce6262553f81cac383cd2016328f5585"},{"author":{"_account_id":9152,"name":"Castulo J. Martinez","email":"castulo.martinez@intel.com","username":"cas"},"change_message_id":"25fd13f51db0afc4855b41b6973a9e87f9245545","unresolved":false,"context_lines":[{"line_number":57,"context_line":"    def _validate_workspaces(self):"},{"line_number":58,"context_line":"        for workspace in self.workspaces:"},{"line_number":59,"context_line":"            if not os.path.exists(workspace.get(\"path\")):"},{"line_number":60,"context_line":"                self.workspaces.remove(workspace)"},{"line_number":61,"context_line":"        self._write_file()"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    def _remove_workspace(self, name):"}],"source_content_type":"text/x-python","patch_set":9,"id":"1af94dfe_d5e605af","line":60,"range":{"start_line":60,"start_character":16,"end_line":60,"end_character":49},"updated":"2016-03-17 21:41:10.000000000","message":"I think that if you are going to remove a workspace because the path could not be found in the system then it should be informed to the user or he/she could get very confused on why his workspace disappeared. Actually, if you want to do this kind of path validation then it should be good to do it when registering a new workspace, so if the user uses a bad path to register the workspace the workspace is never created and the user is informed.","commit_id":"9c268311ce6262553f81cac383cd2016328f5585"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"a0639f9805e8d039715d5b64f7fe91c68ac1dc02","unresolved":false,"context_lines":[{"line_number":57,"context_line":"    def _validate_workspaces(self):"},{"line_number":58,"context_line":"        for workspace in self.workspaces:"},{"line_number":59,"context_line":"            if not os.path.exists(workspace.get(\"path\")):"},{"line_number":60,"context_line":"                self.workspaces.remove(workspace)"},{"line_number":61,"context_line":"        self._write_file()"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    def _remove_workspace(self, name):"}],"source_content_type":"text/x-python","patch_set":9,"id":"fa0719c6_7635e944","line":60,"range":{"start_line":60,"start_character":16,"end_line":60,"end_character":49},"in_reply_to":"1af94dfe_d5e605af","updated":"2016-03-21 16:22:12.000000000","message":"The only time that a workspace is deleted is if the path does not resolve. I don\u0027t think that it\u0027s necessary to tell a user that we\u0027re deleting a workspace because it\u0027s pointing at a bad path.","commit_id":"9c268311ce6262553f81cac383cd2016328f5585"},{"author":{"_account_id":9152,"name":"Castulo J. Martinez","email":"castulo.martinez@intel.com","username":"cas"},"change_message_id":"25fd13f51db0afc4855b41b6973a9e87f9245545","unresolved":false,"context_lines":[{"line_number":98,"context_line":"        exit(0)"},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def get_description(self):"},{"line_number":101,"context_line":"        return \u0027Tempest Workspace Actions\u0027"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"    def get_parser(self, prog_name):"},{"line_number":104,"context_line":"        parser \u003d super(TempestWorkspace, self).get_parser(prog_name)"}],"source_content_type":"text/x-python","patch_set":9,"id":"1af94dfe_eb6f1dc3","line":101,"range":{"start_line":101,"start_character":16,"end_line":101,"end_character":41},"updated":"2016-03-17 21:41:10.000000000","message":"To be consistent with the rest of the tempest commands I think you should not capitalize all words, just the first one: Tempest workspace actions","commit_id":"9c268311ce6262553f81cac383cd2016328f5585"},{"author":{"_account_id":9152,"name":"Castulo J. Martinez","email":"castulo.martinez@intel.com","username":"cas"},"change_message_id":"25fd13f51db0afc4855b41b6973a9e87f9245545","unresolved":false,"context_lines":[{"line_number":103,"context_line":"    def get_parser(self, prog_name):"},{"line_number":104,"context_line":"        parser \u003d super(TempestWorkspace, self).get_parser(prog_name)"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"        parser.add_argument(\u0027--workspace-path\u0027, required\u003dFalse, default\u003dNone)"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        subparsers \u003d parser.add_subparsers()"},{"line_number":109,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"1af94dfe_7853a139","line":106,"range":{"start_line":106,"start_character":28,"end_line":106,"end_character":76},"updated":"2016-03-17 21:41:10.000000000","message":"I think it would be nice to add a help message for this argument, that could make easier to understand the difference between --workspace-path and the --path argument within register","commit_id":"9c268311ce6262553f81cac383cd2016328f5585"},{"author":{"_account_id":9152,"name":"Castulo J. Martinez","email":"castulo.martinez@intel.com","username":"cas"},"change_message_id":"25fd13f51db0afc4855b41b6973a9e87f9245545","unresolved":false,"context_lines":[{"line_number":110,"context_line":"        list_parser \u003d subparsers.add_parser(\u0027list\u0027)"},{"line_number":111,"context_line":"        list_parser.set_defaults(list\u003dTrue)"},{"line_number":112,"context_line":""},{"line_number":113,"context_line":"        register_parser \u003d subparsers.add_parser(\u0027register\u0027, )"},{"line_number":114,"context_line":"        register_parser.add_argument(\u0027--name\u0027, required\u003dTrue)"},{"line_number":115,"context_line":"        register_parser.add_argument(\u0027--path\u0027, required\u003dTrue)"},{"line_number":116,"context_line":"        register_parser.set_defaults(register\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":9,"id":"1af94dfe_38af592b","line":113,"range":{"start_line":113,"start_character":58,"end_line":113,"end_character":60},"updated":"2016-03-17 21:41:10.000000000","message":"not important... but you left a coma here","commit_id":"9c268311ce6262553f81cac383cd2016328f5585"},{"author":{"_account_id":9152,"name":"Castulo J. Martinez","email":"castulo.martinez@intel.com","username":"cas"},"change_message_id":"25fd13f51db0afc4855b41b6973a9e87f9245545","unresolved":false,"context_lines":[{"line_number":116,"context_line":"        register_parser.set_defaults(register\u003dTrue)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"        update_parser \u003d subparsers.add_parser(\u0027update\u0027)"},{"line_number":119,"context_line":"        update_parser.add_argument(\u0027--key\u0027, required\u003dTrue)"},{"line_number":120,"context_line":"        update_parser.add_argument(\u0027--old-value\u0027, required\u003dTrue)"},{"line_number":121,"context_line":"        update_parser.add_argument(\u0027--new-value\u0027, required\u003dTrue)"},{"line_number":122,"context_line":"        update_parser.set_defaults(update\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":9,"id":"1af94dfe_638bf6c3","line":119,"range":{"start_line":119,"start_character":8,"end_line":119,"end_character":58},"updated":"2016-03-17 21:41:10.000000000","message":"I think using the --key argument for updating a workspace could be confusing for the user, he would need to think on the table as a dictionary for that to make sense. Maybe could be clearer if adding an id to each workspace and referring to the workspace by id? something like:\ntempest workspace update --id 1 --old-value old_name --new-value new_name \ntempest workspace update --id 1 --old-value old_path --new-value new_path\n\nHehe just a suggestion Stephen, I\u0027m not trying to give you a hard time :P","commit_id":"9c268311ce6262553f81cac383cd2016328f5585"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"a0639f9805e8d039715d5b64f7fe91c68ac1dc02","unresolved":false,"context_lines":[{"line_number":116,"context_line":"        register_parser.set_defaults(register\u003dTrue)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"        update_parser \u003d subparsers.add_parser(\u0027update\u0027)"},{"line_number":119,"context_line":"        update_parser.add_argument(\u0027--key\u0027, required\u003dTrue)"},{"line_number":120,"context_line":"        update_parser.add_argument(\u0027--old-value\u0027, required\u003dTrue)"},{"line_number":121,"context_line":"        update_parser.add_argument(\u0027--new-value\u0027, required\u003dTrue)"},{"line_number":122,"context_line":"        update_parser.set_defaults(update\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":9,"id":"fa0719c6_f6fc5940","line":119,"range":{"start_line":119,"start_character":8,"end_line":119,"end_character":58},"in_reply_to":"1af94dfe_638bf6c3","updated":"2016-03-21 16:22:12.000000000","message":"That implementation wouldn\u0027t work. There\u0027s nothing to differentiate which value you are changing there.\n\nAlso there\u0027s no concept of id\u0027s tagged to workspaces. It\u0027s just a structure containing name \u0026 path.\n\nPlease refer to the spec: https://github.com/openstack/qa-specs/blob/master/specs/tempest/centralized-workspaces.rst","commit_id":"9c268311ce6262553f81cac383cd2016328f5585"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"3190e47dc20a40bc08077ce80cfec64788524b08","unresolved":false,"context_lines":[{"line_number":111,"context_line":"        parser.add_argument("},{"line_number":112,"context_line":"            \u0027--workspace-path\u0027, required\u003dFalse, default\u003dNone,"},{"line_number":113,"context_line":"            help\u003d\"The path to the workspace file, the default is \""},{"line_number":114,"context_line":"                 \"~/home/.tempest/workspace\")"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"        subparsers \u003d parser.add_subparsers()"},{"line_number":117,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"dab17558_895031d6","line":114,"range":{"start_line":114,"start_character":19,"end_line":114,"end_character":24},"updated":"2016-05-16 10:07:04.000000000","message":"just \"~/.tempest/workspace\"?","commit_id":"415b17662328c40a9eda52a921df0a9730817e59"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"4edeb6aa091159d2b23d15a89922e9f64dc0ed35","unresolved":false,"context_lines":[{"line_number":111,"context_line":"        parser.add_argument("},{"line_number":112,"context_line":"            \u0027--workspace-path\u0027, required\u003dFalse, default\u003dNone,"},{"line_number":113,"context_line":"            help\u003d\"The path to the workspace file, the default is \""},{"line_number":114,"context_line":"                 \"~/home/.tempest/workspace\")"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"        subparsers \u003d parser.add_subparsers()"},{"line_number":117,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"dab17558_5194d089","line":114,"range":{"start_line":114,"start_character":19,"end_line":114,"end_character":24},"in_reply_to":"dab17558_895031d6","updated":"2016-05-16 14:37:46.000000000","message":"Done","commit_id":"415b17662328c40a9eda52a921df0a9730817e59"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"705549404426225c874c65c99ea17bd69b816db1","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        self.workspaces \u003d []"},{"line_number":33,"context_line":"        self._populate()"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def get_workspace(self, name):"},{"line_number":36,"context_line":"        for workspace in self.workspaces:"},{"line_number":37,"context_line":"            if workspace.get(\"name\") \u003d\u003d name:"},{"line_number":38,"context_line":"                return workspace"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    def update_workspace(self, key, old, new):"},{"line_number":41,"context_line":"        for workspace in self.workspaces:"}],"source_content_type":"text/x-python","patch_set":12,"id":"dab17558_c23c4be3","line":38,"range":{"start_line":35,"start_character":0,"end_line":38,"end_character":32},"updated":"2016-05-17 08:11:21.000000000","message":"This method is used in only test cases. I\u0027m unsure this is intended or not. But if you think this is for only test cases, I think we should add a comment for that.","commit_id":"0dc3aef6caa4f1482a79ec76bdbe6fbbcf8766cd"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"c44f7bafa4c459c4897d65be933a23b5b6ef1006","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        self.workspaces \u003d []"},{"line_number":33,"context_line":"        self._populate()"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def get_workspace(self, name):"},{"line_number":36,"context_line":"        for workspace in self.workspaces:"},{"line_number":37,"context_line":"            if workspace.get(\"name\") \u003d\u003d name:"},{"line_number":38,"context_line":"                return workspace"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    def update_workspace(self, key, old, new):"},{"line_number":41,"context_line":"        for workspace in self.workspaces:"}],"source_content_type":"text/x-python","patch_set":12,"id":"dab17558_49e9857e","line":38,"range":{"start_line":35,"start_character":0,"end_line":38,"end_character":32},"in_reply_to":"dab17558_c23c4be3","updated":"2016-05-17 15:06:28.000000000","message":"This is intended to be used by other tooling (tempest run) so that they don\u0027t have to interact with the workspace list directly when locating a workspace by name.","commit_id":"0dc3aef6caa4f1482a79ec76bdbe6fbbcf8766cd"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"705549404426225c874c65c99ea17bd69b816db1","unresolved":false,"context_lines":[{"line_number":62,"context_line":"    def _validate_workspaces(self):"},{"line_number":63,"context_line":"        for workspace in self.workspaces:"},{"line_number":64,"context_line":"            if not os.path.exists(workspace.get(\"path\")):"},{"line_number":65,"context_line":"                self.workspaces.remove(workspace)"},{"line_number":66,"context_line":"        self._write_file()"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def _remove_workspace(self, name):"}],"source_content_type":"text/x-python","patch_set":12,"id":"dab17558_18e08428","line":65,"range":{"start_line":65,"start_character":16,"end_line":65,"end_character":49},"updated":"2016-05-17 08:11:21.000000000","message":"hmm, this is not good for this loop because this shrink this list and we can\u0027t access rest one. For example,\n\n-------\n workspaces \u003d [{\u0027path\u0027: \u0027/Users/igawa/cloud1\u0027, \u0027name\u0027: \u0027cloud1\u0027}, {\u0027path\u0027: \u0027/Users/igawa/cloud2\u0027, \u0027name\u0027: \u0027cloud2\u0027}, {\u0027path\u0027: \u0027/Users/igawa/cloud3\u0027, \u0027name\u0027: \u0027cloud3\u0027}]\n\nWhen /Users/igawa/cloud2 and 3 don\u0027t exist, cloud3 doesn\u0027t remove with this logic.\n\n\nSo, how about like this?\n\n workspaces \u003d [workspace for workspace in workspaces if os.path.exists(workspace.get(\"path\"))]","commit_id":"0dc3aef6caa4f1482a79ec76bdbe6fbbcf8766cd"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"c44f7bafa4c459c4897d65be933a23b5b6ef1006","unresolved":false,"context_lines":[{"line_number":62,"context_line":"    def _validate_workspaces(self):"},{"line_number":63,"context_line":"        for workspace in self.workspaces:"},{"line_number":64,"context_line":"            if not os.path.exists(workspace.get(\"path\")):"},{"line_number":65,"context_line":"                self.workspaces.remove(workspace)"},{"line_number":66,"context_line":"        self._write_file()"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def _remove_workspace(self, name):"}],"source_content_type":"text/x-python","patch_set":12,"id":"dab17558_44b5ecea","line":65,"range":{"start_line":65,"start_character":16,"end_line":65,"end_character":49},"in_reply_to":"dab17558_18e08428","updated":"2016-05-17 15:06:28.000000000","message":"Done","commit_id":"0dc3aef6caa4f1482a79ec76bdbe6fbbcf8766cd"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"705549404426225c874c65c99ea17bd69b816db1","unresolved":false,"context_lines":[{"line_number":65,"context_line":"                self.workspaces.remove(workspace)"},{"line_number":66,"context_line":"        self._write_file()"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def _remove_workspace(self, name):"},{"line_number":69,"context_line":"        for workspace in self.workspaces:"},{"line_number":70,"context_line":"            if workspace.get(\"name\") \u003d\u003d name:"},{"line_number":71,"context_line":"                self.workspaces.remove(workspace)"},{"line_number":72,"context_line":"                self._write_file()"},{"line_number":73,"context_line":"                return"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    def _write_file(self):"},{"line_number":76,"context_line":"        with open(self.path, \u0027w\u0027) as f:"}],"source_content_type":"text/x-python","patch_set":12,"id":"dab17558_22055745","line":73,"range":{"start_line":68,"start_character":0,"end_line":73,"end_character":22},"updated":"2016-05-17 08:11:21.000000000","message":"ditto, this method is also unused in this class.","commit_id":"0dc3aef6caa4f1482a79ec76bdbe6fbbcf8766cd"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"c44f7bafa4c459c4897d65be933a23b5b6ef1006","unresolved":false,"context_lines":[{"line_number":65,"context_line":"                self.workspaces.remove(workspace)"},{"line_number":66,"context_line":"        self._write_file()"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def _remove_workspace(self, name):"},{"line_number":69,"context_line":"        for workspace in self.workspaces:"},{"line_number":70,"context_line":"            if workspace.get(\"name\") \u003d\u003d name:"},{"line_number":71,"context_line":"                self.workspaces.remove(workspace)"},{"line_number":72,"context_line":"                self._write_file()"},{"line_number":73,"context_line":"                return"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    def _write_file(self):"},{"line_number":76,"context_line":"        with open(self.path, \u0027w\u0027) as f:"}],"source_content_type":"text/x-python","patch_set":12,"id":"dab17558_44104c00","line":73,"range":{"start_line":68,"start_character":0,"end_line":73,"end_character":22},"in_reply_to":"dab17558_22055745","updated":"2016-05-17 15:06:28.000000000","message":"Done, moved the logic into the unittest class.","commit_id":"0dc3aef6caa4f1482a79ec76bdbe6fbbcf8766cd"},{"author":{"_account_id":1921,"name":"Andrea Frittoli","email":"andrea.frittoli@gmail.com","username":"andrea-frittoli"},"change_message_id":"b518441605bd23e9d9a9db6c6448294bdea49a0d","unresolved":false,"context_lines":[{"line_number":39,"context_line":"            if workspace.get(\"name\") \u003d\u003d name:"},{"line_number":40,"context_line":"                return workspace"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def update_workspace(self, key, old, new):"},{"line_number":43,"context_line":"        for workspace in self.workspaces:"},{"line_number":44,"context_line":"            if workspace.get(key) \u003d\u003d old:"},{"line_number":45,"context_line":"                workspace.update({key: new})"}],"source_content_type":"text/x-python","patch_set":15,"id":"bab6814e_ae4d2974","line":42,"updated":"2016-05-19 10:14:19.000000000","message":"This allows updating both the name and path, but you do not enforce name uniqueness nor path existence like in other places.","commit_id":"3de9633b20fde38ff9bf9c9120f1b2ea83c2448b"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"2801fd9a178277c1b24d7b8416b791f43fdf7866","unresolved":false,"context_lines":[{"line_number":39,"context_line":"            if workspace.get(\"name\") \u003d\u003d name:"},{"line_number":40,"context_line":"                return workspace"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def update_workspace(self, key, old, new):"},{"line_number":43,"context_line":"        for workspace in self.workspaces:"},{"line_number":44,"context_line":"            if workspace.get(key) \u003d\u003d old:"},{"line_number":45,"context_line":"                workspace.update({key: new})"}],"source_content_type":"text/x-python","patch_set":15,"id":"bab6814e_706f4c2b","line":42,"in_reply_to":"bab6814e_ae4d2974","updated":"2016-05-20 14:39:42.000000000","message":"Done","commit_id":"3de9633b20fde38ff9bf9c9120f1b2ea83c2448b"},{"author":{"_account_id":1921,"name":"Andrea Frittoli","email":"andrea.frittoli@gmail.com","username":"andrea-frittoli"},"change_message_id":"b518441605bd23e9d9a9db6c6448294bdea49a0d","unresolved":false,"context_lines":[{"line_number":64,"context_line":"        self._write_file()"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    def _validate_workspaces(self):"},{"line_number":67,"context_line":"        self.workspaces \u003d [workspace for workspace in self.workspaces"},{"line_number":68,"context_line":"                           if os.path.exists(workspace.get(\"path\"))]"},{"line_number":69,"context_line":"        self._write_file()"},{"line_number":70,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"bab6814e_239f9251","line":67,"updated":"2016-05-19 10:14:19.000000000","message":"I\u0027m not sure about this. If I get it right, the moment the path of a configured workspace goes away you\u0027re pruning it away from the workspaces file.\nThis could lead to unexpected behaviours - I would prefer having an explicit \"prune\" option. Also the only way to delete a workspace is to delete the files.\nI think we should have a delete command instead.","commit_id":"3de9633b20fde38ff9bf9c9120f1b2ea83c2448b"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"88facce35e151727fd6705807e7dd5f12eb69e3b","unresolved":false,"context_lines":[{"line_number":64,"context_line":"        self._write_file()"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    def _validate_workspaces(self):"},{"line_number":67,"context_line":"        self.workspaces \u003d [workspace for workspace in self.workspaces"},{"line_number":68,"context_line":"                           if os.path.exists(workspace.get(\"path\"))]"},{"line_number":69,"context_line":"        self._write_file()"},{"line_number":70,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"bab6814e_e592f24a","line":67,"in_reply_to":"bab6814e_239f9251","updated":"2016-05-24 06:04:38.000000000","message":"Actually, this was talked[1] in the qa-spec review as Stephen said. And I don\u0027t understand what is \u0027unexpected behaviours\u0027. Why do we need an explicit \u0027prune\u0027 option? Do you have a concrete workflow here?\n\n[1] https://review.openstack.org/#/c/266094/1/specs/tempest/centralized-workspaces.rst@40","commit_id":"3de9633b20fde38ff9bf9c9120f1b2ea83c2448b"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"2801fd9a178277c1b24d7b8416b791f43fdf7866","unresolved":false,"context_lines":[{"line_number":64,"context_line":"        self._write_file()"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    def _validate_workspaces(self):"},{"line_number":67,"context_line":"        self.workspaces \u003d [workspace for workspace in self.workspaces"},{"line_number":68,"context_line":"                           if os.path.exists(workspace.get(\"path\"))]"},{"line_number":69,"context_line":"        self._write_file()"},{"line_number":70,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"bab6814e_107080db","line":67,"in_reply_to":"bab6814e_239f9251","updated":"2016-05-20 14:39:42.000000000","message":"I\u0027ll re-add a delete subcommand, however, I believe it was mtreinish who asked for this functionality in the spec review.","commit_id":"3de9633b20fde38ff9bf9c9120f1b2ea83c2448b"},{"author":{"_account_id":1921,"name":"Andrea Frittoli","email":"andrea.frittoli@gmail.com","username":"andrea-frittoli"},"change_message_id":"b518441605bd23e9d9a9db6c6448294bdea49a0d","unresolved":false,"context_lines":[{"line_number":68,"context_line":"                           if os.path.exists(workspace.get(\"path\"))]"},{"line_number":69,"context_line":"        self._write_file()"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    def _write_file(self):"},{"line_number":72,"context_line":"        with open(self.path, \u0027w\u0027) as f:"},{"line_number":73,"context_line":"            for workspace in self.workspaces:"},{"line_number":74,"context_line":"                f.write(\"{0}\u003d{1}\\n\".format("},{"line_number":75,"context_line":"                    workspace.get(\"name\"), workspace.get(\"path\")))"}],"source_content_type":"text/x-python","patch_set":15,"id":"bab6814e_ceea2dac","line":72,"range":{"start_line":71,"start_character":4,"end_line":72,"end_character":39},"updated":"2016-05-19 10:14:19.000000000","message":"I think we should have file locking in place, or at a minimum document that this command is not thread/process safe. If the tempest workspace command is executed in parallel on a system it could lead to inconsistent results.","commit_id":"3de9633b20fde38ff9bf9c9120f1b2ea83c2448b"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"88facce35e151727fd6705807e7dd5f12eb69e3b","unresolved":false,"context_lines":[{"line_number":68,"context_line":"                           if os.path.exists(workspace.get(\"path\"))]"},{"line_number":69,"context_line":"        self._write_file()"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    def _write_file(self):"},{"line_number":72,"context_line":"        with open(self.path, \u0027w\u0027) as f:"},{"line_number":73,"context_line":"            for workspace in self.workspaces:"},{"line_number":74,"context_line":"                f.write(\"{0}\u003d{1}\\n\".format("},{"line_number":75,"context_line":"                    workspace.get(\"name\"), workspace.get(\"path\")))"}],"source_content_type":"text/x-python","patch_set":15,"id":"bab6814e_05ed768e","line":72,"range":{"start_line":71,"start_character":4,"end_line":72,"end_character":39},"in_reply_to":"bab6814e_8792584a","updated":"2016-05-24 06:04:38.000000000","message":"ah, I didn\u0027t noticed the workflow.., Nice catch.\nSo, if we introduce a locking feature, like this?\n\n with open(self.path, \u0027w\u0027) as f:\n   fcntl.flock(f, fcntl.LOCK_EX)\n   try:\n     for workspace in self.workspaces:\n       f.write(..............)\n   finally\n     fcntl.flock(f, fcntl.LOCK_UN)","commit_id":"3de9633b20fde38ff9bf9c9120f1b2ea83c2448b"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"2801fd9a178277c1b24d7b8416b791f43fdf7866","unresolved":false,"context_lines":[{"line_number":68,"context_line":"                           if os.path.exists(workspace.get(\"path\"))]"},{"line_number":69,"context_line":"        self._write_file()"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    def _write_file(self):"},{"line_number":72,"context_line":"        with open(self.path, \u0027w\u0027) as f:"},{"line_number":73,"context_line":"            for workspace in self.workspaces:"},{"line_number":74,"context_line":"                f.write(\"{0}\u003d{1}\\n\".format("},{"line_number":75,"context_line":"                    workspace.get(\"name\"), workspace.get(\"path\")))"}],"source_content_type":"text/x-python","patch_set":15,"id":"bab6814e_d018b8d5","line":72,"range":{"start_line":71,"start_character":4,"end_line":72,"end_character":39},"in_reply_to":"bab6814e_ceea2dac","updated":"2016-05-20 14:39:42.000000000","message":"I can add some documentation that it isn\u0027t thread safe but I don\u0027t understand why this class would ever be used in parallel.\n\nIn a parallel run situation this class should be used during the initial entrypoint before any of the children thread are spawned off to get the location of the tempest config files. After that I\u0027m unsure why anything would be calling in here.","commit_id":"3de9633b20fde38ff9bf9c9120f1b2ea83c2448b"},{"author":{"_account_id":1921,"name":"Andrea Frittoli","email":"andrea.frittoli@gmail.com","username":"andrea-frittoli"},"change_message_id":"e44b19aa85c937cc30ed27876690a1117c805d44","unresolved":false,"context_lines":[{"line_number":68,"context_line":"                           if os.path.exists(workspace.get(\"path\"))]"},{"line_number":69,"context_line":"        self._write_file()"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    def _write_file(self):"},{"line_number":72,"context_line":"        with open(self.path, \u0027w\u0027) as f:"},{"line_number":73,"context_line":"            for workspace in self.workspaces:"},{"line_number":74,"context_line":"                f.write(\"{0}\u003d{1}\\n\".format("},{"line_number":75,"context_line":"                    workspace.get(\"name\"), workspace.get(\"path\")))"}],"source_content_type":"text/x-python","patch_set":15,"id":"bab6814e_8792584a","line":72,"range":{"start_line":71,"start_character":4,"end_line":72,"end_character":39},"in_reply_to":"bab6814e_d018b8d5","updated":"2016-05-21 22:07:53.000000000","message":"I was thinking of the case of many \"tempest workspace xyz\" commands running in parallel. If automated jobs are running on a server and they execute workflow commands as part of their workflow, they may try to edit the workflow config in parallel.","commit_id":"3de9633b20fde38ff9bf9c9120f1b2ea83c2448b"},{"author":{"_account_id":1921,"name":"Andrea Frittoli","email":"andrea.frittoli@gmail.com","username":"andrea-frittoli"},"change_message_id":"b518441605bd23e9d9a9db6c6448294bdea49a0d","unresolved":false,"context_lines":[{"line_number":117,"context_line":"        register_parser.add_argument(\u0027--path\u0027, required\u003dTrue)"},{"line_number":118,"context_line":"        register_parser.set_defaults(register\u003dTrue)"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"        update_parser \u003d subparsers.add_parser(\u0027update\u0027)"},{"line_number":121,"context_line":"        update_parser.add_argument(\u0027--key\u0027, required\u003dTrue)"},{"line_number":122,"context_line":"        update_parser.add_argument(\u0027--old-value\u0027, required\u003dTrue)"},{"line_number":123,"context_line":"        update_parser.add_argument(\u0027--new-value\u0027, required\u003dTrue)"},{"line_number":124,"context_line":"        update_parser.set_defaults(update\u003dTrue)"},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"        return parser"}],"source_content_type":"text/x-python","patch_set":15,"id":"bab6814e_6e1b411c","line":123,"range":{"start_line":120,"start_character":0,"end_line":123,"end_character":64},"updated":"2016-05-19 10:14:19.000000000","message":"I think having two commands, rename and move would make a better user interface. When moving an namespace it should be done by name and not by old-path. There is no restriction against having two names for the same path, so a reference by path would have to update both, but the code above breaks after the first match.","commit_id":"3de9633b20fde38ff9bf9c9120f1b2ea83c2448b"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"2801fd9a178277c1b24d7b8416b791f43fdf7866","unresolved":false,"context_lines":[{"line_number":117,"context_line":"        register_parser.add_argument(\u0027--path\u0027, required\u003dTrue)"},{"line_number":118,"context_line":"        register_parser.set_defaults(register\u003dTrue)"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"        update_parser \u003d subparsers.add_parser(\u0027update\u0027)"},{"line_number":121,"context_line":"        update_parser.add_argument(\u0027--key\u0027, required\u003dTrue)"},{"line_number":122,"context_line":"        update_parser.add_argument(\u0027--old-value\u0027, required\u003dTrue)"},{"line_number":123,"context_line":"        update_parser.add_argument(\u0027--new-value\u0027, required\u003dTrue)"},{"line_number":124,"context_line":"        update_parser.set_defaults(update\u003dTrue)"},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"        return parser"}],"source_content_type":"text/x-python","patch_set":15,"id":"bab6814e_100fe088","line":123,"range":{"start_line":120,"start_character":0,"end_line":123,"end_character":64},"in_reply_to":"bab6814e_6e1b411c","updated":"2016-05-20 14:39:42.000000000","message":"Done","commit_id":"3de9633b20fde38ff9bf9c9120f1b2ea83c2448b"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6143be02a97f3835e471016f98a5e4656f23fe49","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"class WorkspaceManager(object):"},{"line_number":30,"context_line":"    def __init__(self, path\u003dNone):"},{"line_number":31,"context_line":"        self.lock_path \u003d lockutils.get_lock_path(CONF)"},{"line_number":32,"context_line":"        self.path \u003d path or os.path.join("},{"line_number":33,"context_line":"            os.environ.get(\"HOME\"), \".tempest\", \"workspace\")"},{"line_number":34,"context_line":"        if not os.path.exists(self.path.rsplit(os.path.sep, 1)[0]):"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_4f3bf09c","line":31,"updated":"2016-05-24 19:14:02.000000000","message":"What is this used for?","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":1921,"name":"Andrea Frittoli","email":"andrea.frittoli@gmail.com","username":"andrea-frittoli"},"change_message_id":"ed18e8af801597d732e08b32d66589f828d31b27","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"class WorkspaceManager(object):"},{"line_number":30,"context_line":"    def __init__(self, path\u003dNone):"},{"line_number":31,"context_line":"        self.lock_path \u003d lockutils.get_lock_path(CONF)"},{"line_number":32,"context_line":"        self.path \u003d path or os.path.join("},{"line_number":33,"context_line":"            os.environ.get(\"HOME\"), \".tempest\", \"workspace\")"},{"line_number":34,"context_line":"        if not os.path.exists(self.path.rsplit(os.path.sep, 1)[0]):"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_cb1a317c","line":31,"in_reply_to":"bab6814e_4f3bf09c","updated":"2016-05-24 20:31:54.000000000","message":"I think this is because I asked for locking in case multiple tempest workspace commands are executed in parallel to avoid corrupting the config file.","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"3bbb8c910f559b2cef5de2143b273cd2dffe22b9","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"class WorkspaceManager(object):"},{"line_number":30,"context_line":"    def __init__(self, path\u003dNone):"},{"line_number":31,"context_line":"        self.lock_path \u003d lockutils.get_lock_path(CONF)"},{"line_number":32,"context_line":"        self.path \u003d path or os.path.join("},{"line_number":33,"context_line":"            os.environ.get(\"HOME\"), \".tempest\", \"workspace\")"},{"line_number":34,"context_line":"        if not os.path.exists(self.path.rsplit(os.path.sep, 1)[0]):"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_ea01f23a","line":31,"in_reply_to":"bab6814e_4f3bf09c","updated":"2016-05-24 20:43:29.000000000","message":"Without it an error is thrown. I can remove the setting of it into a variable but the lockutils.get_lock_path(CONF) has to be run.\n\n  \u003e tempest workspace list\n  value required for option: lock_path","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6143be02a97f3835e471016f98a5e4656f23fe49","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    def __init__(self, path\u003dNone):"},{"line_number":31,"context_line":"        self.lock_path \u003d lockutils.get_lock_path(CONF)"},{"line_number":32,"context_line":"        self.path \u003d path or os.path.join("},{"line_number":33,"context_line":"            os.environ.get(\"HOME\"), \".tempest\", \"workspace\")"},{"line_number":34,"context_line":"        if not os.path.exists(self.path.rsplit(os.path.sep, 1)[0]):"},{"line_number":35,"context_line":"            os.makedirs(self.path.rsplit(os.path.sep, 1)[0])"},{"line_number":36,"context_line":"        if not os.path.exists(self.path):"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_2f6cac9b","line":33,"updated":"2016-05-24 19:14:02.000000000","message":"We probably should use expanduser here:\n\nhttps://docs.python.org/2.7/library/os.path.html#os.path.expanduser","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"3bbb8c910f559b2cef5de2143b273cd2dffe22b9","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    def __init__(self, path\u003dNone):"},{"line_number":31,"context_line":"        self.lock_path \u003d lockutils.get_lock_path(CONF)"},{"line_number":32,"context_line":"        self.path \u003d path or os.path.join("},{"line_number":33,"context_line":"            os.environ.get(\"HOME\"), \".tempest\", \"workspace\")"},{"line_number":34,"context_line":"        if not os.path.exists(self.path.rsplit(os.path.sep, 1)[0]):"},{"line_number":35,"context_line":"            os.makedirs(self.path.rsplit(os.path.sep, 1)[0])"},{"line_number":36,"context_line":"        if not os.path.exists(self.path):"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_ca086e30","line":33,"in_reply_to":"bab6814e_2f6cac9b","updated":"2016-05-24 20:43:29.000000000","message":"Done","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6143be02a97f3835e471016f98a5e4656f23fe49","unresolved":false,"context_lines":[{"line_number":31,"context_line":"        self.lock_path \u003d lockutils.get_lock_path(CONF)"},{"line_number":32,"context_line":"        self.path \u003d path or os.path.join("},{"line_number":33,"context_line":"            os.environ.get(\"HOME\"), \".tempest\", \"workspace\")"},{"line_number":34,"context_line":"        if not os.path.exists(self.path.rsplit(os.path.sep, 1)[0]):"},{"line_number":35,"context_line":"            os.makedirs(self.path.rsplit(os.path.sep, 1)[0])"},{"line_number":36,"context_line":"        if not os.path.exists(self.path):"},{"line_number":37,"context_line":"            open(self.path, \u0027a\u0027).close()"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_efe62415","line":34,"updated":"2016-05-24 19:14:02.000000000","message":"Why not just use os.path.isdir(os.dirname(self.path)):","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"3bbb8c910f559b2cef5de2143b273cd2dffe22b9","unresolved":false,"context_lines":[{"line_number":31,"context_line":"        self.lock_path \u003d lockutils.get_lock_path(CONF)"},{"line_number":32,"context_line":"        self.path \u003d path or os.path.join("},{"line_number":33,"context_line":"            os.environ.get(\"HOME\"), \".tempest\", \"workspace\")"},{"line_number":34,"context_line":"        if not os.path.exists(self.path.rsplit(os.path.sep, 1)[0]):"},{"line_number":35,"context_line":"            os.makedirs(self.path.rsplit(os.path.sep, 1)[0])"},{"line_number":36,"context_line":"        if not os.path.exists(self.path):"},{"line_number":37,"context_line":"            open(self.path, \u0027a\u0027).close()"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_2a065a20","line":34,"in_reply_to":"bab6814e_efe62415","updated":"2016-05-24 20:43:29.000000000","message":"Done","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6143be02a97f3835e471016f98a5e4656f23fe49","unresolved":false,"context_lines":[{"line_number":33,"context_line":"            os.environ.get(\"HOME\"), \".tempest\", \"workspace\")"},{"line_number":34,"context_line":"        if not os.path.exists(self.path.rsplit(os.path.sep, 1)[0]):"},{"line_number":35,"context_line":"            os.makedirs(self.path.rsplit(os.path.sep, 1)[0])"},{"line_number":36,"context_line":"        if not os.path.exists(self.path):"},{"line_number":37,"context_line":"            open(self.path, \u0027a\u0027).close()"},{"line_number":38,"context_line":"        self.workspaces \u003d []"},{"line_number":39,"context_line":"        self._populate()"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_8fb838e7","line":36,"updated":"2016-05-24 19:14:02.000000000","message":"Why do we need to do this? Won\u0027t we just create the file when we open it to write to?","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"3bbb8c910f559b2cef5de2143b273cd2dffe22b9","unresolved":false,"context_lines":[{"line_number":33,"context_line":"            os.environ.get(\"HOME\"), \".tempest\", \"workspace\")"},{"line_number":34,"context_line":"        if not os.path.exists(self.path.rsplit(os.path.sep, 1)[0]):"},{"line_number":35,"context_line":"            os.makedirs(self.path.rsplit(os.path.sep, 1)[0])"},{"line_number":36,"context_line":"        if not os.path.exists(self.path):"},{"line_number":37,"context_line":"            open(self.path, \u0027a\u0027).close()"},{"line_number":38,"context_line":"        self.workspaces \u003d []"},{"line_number":39,"context_line":"        self._populate()"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_280ca393","line":36,"in_reply_to":"bab6814e_8fb838e7","updated":"2016-05-24 20:43:29.000000000","message":"Done","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6143be02a97f3835e471016f98a5e4656f23fe49","unresolved":false,"context_lines":[{"line_number":35,"context_line":"            os.makedirs(self.path.rsplit(os.path.sep, 1)[0])"},{"line_number":36,"context_line":"        if not os.path.exists(self.path):"},{"line_number":37,"context_line":"            open(self.path, \u0027a\u0027).close()"},{"line_number":38,"context_line":"        self.workspaces \u003d []"},{"line_number":39,"context_line":"        self._populate()"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    def get_workspace(self, name):"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_cf69a027","line":38,"updated":"2016-05-24 19:14:02.000000000","message":"Why not just make this a single dict with the key being name and the value being the path? It\u0027s not like there are more attrs we want to set, and even if we did we could make it a dict of dicts. The use of a list seems a little weird here.","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":1921,"name":"Andrea Frittoli","email":"andrea.frittoli@gmail.com","username":"andrea-frittoli"},"change_message_id":"ed18e8af801597d732e08b32d66589f828d31b27","unresolved":false,"context_lines":[{"line_number":35,"context_line":"            os.makedirs(self.path.rsplit(os.path.sep, 1)[0])"},{"line_number":36,"context_line":"        if not os.path.exists(self.path):"},{"line_number":37,"context_line":"            open(self.path, \u0027a\u0027).close()"},{"line_number":38,"context_line":"        self.workspaces \u003d []"},{"line_number":39,"context_line":"        self._populate()"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    def get_workspace(self, name):"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_2e202b9b","line":38,"in_reply_to":"bab6814e_cf69a027","updated":"2016-05-24 20:31:54.000000000","message":"+1 - there are checks below in the code to enforce name uniqueness, so using a dict here would make them more efficient.","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"3bbb8c910f559b2cef5de2143b273cd2dffe22b9","unresolved":false,"context_lines":[{"line_number":35,"context_line":"            os.makedirs(self.path.rsplit(os.path.sep, 1)[0])"},{"line_number":36,"context_line":"        if not os.path.exists(self.path):"},{"line_number":37,"context_line":"            open(self.path, \u0027a\u0027).close()"},{"line_number":38,"context_line":"        self.workspaces \u003d []"},{"line_number":39,"context_line":"        self._populate()"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    def get_workspace(self, name):"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_c87b57f3","line":38,"in_reply_to":"bab6814e_cf69a027","updated":"2016-05-24 20:43:29.000000000","message":"Done","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6143be02a97f3835e471016f98a5e4656f23fe49","unresolved":false,"context_lines":[{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    @lockutils.synchronized(\u0027workspaces\u0027, external\u003dTrue)"},{"line_number":94,"context_line":"    def _write_file(self):"},{"line_number":95,"context_line":"        with open(self.path, \u0027w\u0027) as f:"},{"line_number":96,"context_line":"            for workspace in self.workspaces:"},{"line_number":97,"context_line":"                f.write(\"{0}\u003d{1}\\n\".format("},{"line_number":98,"context_line":"                    workspace.get(\"name\"), workspace.get(\"path\")))"},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    @lockutils.synchronized(\u0027workspaces\u0027, external\u003dTrue)"},{"line_number":101,"context_line":"    def _populate(self):"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_8f1038aa","line":98,"range":{"start_line":95,"start_character":8,"end_line":98,"end_character":66},"updated":"2016-05-24 19:14:02.000000000","message":"I think this whole block would be easier to just do with yaml instead of having to maintain our own format. So just do something like:\n\n  with open(self.path, \u0027w\u0027) as f:\n    yaml.dump(self.workspaces)","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"3bbb8c910f559b2cef5de2143b273cd2dffe22b9","unresolved":false,"context_lines":[{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    @lockutils.synchronized(\u0027workspaces\u0027, external\u003dTrue)"},{"line_number":94,"context_line":"    def _write_file(self):"},{"line_number":95,"context_line":"        with open(self.path, \u0027w\u0027) as f:"},{"line_number":96,"context_line":"            for workspace in self.workspaces:"},{"line_number":97,"context_line":"                f.write(\"{0}\u003d{1}\\n\".format("},{"line_number":98,"context_line":"                    workspace.get(\"name\"), workspace.get(\"path\")))"},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    @lockutils.synchronized(\u0027workspaces\u0027, external\u003dTrue)"},{"line_number":101,"context_line":"    def _populate(self):"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_881b0fca","line":98,"range":{"start_line":95,"start_character":8,"end_line":98,"end_character":66},"in_reply_to":"bab6814e_8f1038aa","updated":"2016-05-24 20:43:29.000000000","message":"Done","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6143be02a97f3835e471016f98a5e4656f23fe49","unresolved":false,"context_lines":[{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    @lockutils.synchronized(\u0027workspaces\u0027, external\u003dTrue)"},{"line_number":101,"context_line":"    def _populate(self):"},{"line_number":102,"context_line":"        with open(self.path, \u0027r\u0027) as f:"},{"line_number":103,"context_line":"            for line in f.read().split(\"\\n\"):"},{"line_number":104,"context_line":"                if line !\u003d \"\":"},{"line_number":105,"context_line":"                    name, path \u003d line.split(\"\u003d\")"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_2f778c03","line":102,"updated":"2016-05-24 19:14:02.000000000","message":"Oh, I see the os.path.exists above is because you\u0027re seperating reads from writes. If this is the case we should just add an isfile() call here and just return.","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"3bbb8c910f559b2cef5de2143b273cd2dffe22b9","unresolved":false,"context_lines":[{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    @lockutils.synchronized(\u0027workspaces\u0027, external\u003dTrue)"},{"line_number":101,"context_line":"    def _populate(self):"},{"line_number":102,"context_line":"        with open(self.path, \u0027r\u0027) as f:"},{"line_number":103,"context_line":"            for line in f.read().split(\"\\n\"):"},{"line_number":104,"context_line":"                if line !\u003d \"\":"},{"line_number":105,"context_line":"                    name, path \u003d line.split(\"\u003d\")"}],"source_content_type":"text/x-python","patch_set":19,"id":"bab6814e_482127fc","line":102,"in_reply_to":"bab6814e_2f778c03","updated":"2016-05-24 20:43:29.000000000","message":"Done","commit_id":"561c93d91e2c4bc6c1d55769edbc827af4d73e6e"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"3a785ff0bbafc15abb9299267ec81a440291326f","unresolved":false,"context_lines":[{"line_number":95,"context_line":"        if not init:"},{"line_number":96,"context_line":"            self._validate_path(path)"},{"line_number":97,"context_line":"        self._workspace_name_exists(name)"},{"line_number":98,"context_line":"        self.workspaces[name] \u003d path"},{"line_number":99,"context_line":"        self._write_file()"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    def _validate_workspaces(self):"}],"source_content_type":"text/x-python","patch_set":22,"id":"9abb7d3a_15c77446","line":98,"range":{"start_line":98,"start_character":32,"end_line":98,"end_character":36},"updated":"2016-05-27 06:29:54.000000000","message":"I think we should expand this path like this:\n\n os.path.abspath(os.path.expanduser(path))\n\nBecause there is an issue in the current code like below.\n\n % cd tmp\n % tempest init cloud1\n % tempest workspace list\n +--------+--------+\n |  Name  |  Path  |\n +--------+--------+\n | cloud1 | cloud1 |\n +--------+--------+\n % cd ..\n % tempest workspace list\n +------+------+\n | Name | Path |\n +------+------+\n +------+------+\n\n (cloud1 was removed, unexpectedly.)","commit_id":"bf0afc31ecbf6793d264d8411e7a88975cbc077a"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"5dfbe2d4a0e1be1e959f655f1515f0023ba80dde","unresolved":false,"context_lines":[{"line_number":95,"context_line":"        if not init:"},{"line_number":96,"context_line":"            self._validate_path(path)"},{"line_number":97,"context_line":"        self._workspace_name_exists(name)"},{"line_number":98,"context_line":"        self.workspaces[name] \u003d path"},{"line_number":99,"context_line":"        self._write_file()"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    def _validate_workspaces(self):"}],"source_content_type":"text/x-python","patch_set":22,"id":"9abb7d3a_36442c73","line":98,"range":{"start_line":98,"start_character":32,"end_line":98,"end_character":36},"in_reply_to":"9abb7d3a_15c77446","updated":"2016-05-27 14:18:01.000000000","message":"Done","commit_id":"bf0afc31ecbf6793d264d8411e7a88975cbc077a"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"c193da2fb189150488ef92cbef2275d59ffb0282","unresolved":false,"context_lines":[{"line_number":51,"context_line":"        self._write_file()"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    @lockutils.synchronized(\u0027workspaces\u0027, external\u003dTrue)"},{"line_number":54,"context_line":"    def move_workspace(self, name, path):"},{"line_number":55,"context_line":"        self._populate()"},{"line_number":56,"context_line":"        path \u003d os.path.abspath(os.path.expanduser(path))"},{"line_number":57,"context_line":"        self._name_exists(name)"}],"source_content_type":"text/x-python","patch_set":23,"id":"9abb7d3a_d656df28","line":54,"updated":"2016-06-01 06:09:20.000000000","message":"I was confused this \u0027move\u0027 action at first.\nBut now, I understand this. I think this is a shortcut of \n\n tempest workspace remove --name NAME\n tempest workspace register --name NAME --path NEW-PATH\n\n?\n\nSo, one of possible workflows is\n\n $ mv OLD-TEMPEST-PATH NEW-TEMPEST-PATH\n $ tempest workspace move --name NAME --path NEW-TEMPEST-PATH\n\ninstead of\n\n $ mv OLD-TEMPEST-PATH NEW-TEMPEST-PATH\n $ tempest workspace remove --name NAME\n $ tempest workspace register --name NAME --path NEW-TEMPEST-PATH","commit_id":"dc9f756fda5d3a050927935da82e22cf0c711657"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"62e26446f1b88b7391ea18b2f1ed5690d4f1bac4","unresolved":false,"context_lines":[{"line_number":51,"context_line":"        self._write_file()"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    @lockutils.synchronized(\u0027workspaces\u0027, external\u003dTrue)"},{"line_number":54,"context_line":"    def move_workspace(self, name, path):"},{"line_number":55,"context_line":"        self._populate()"},{"line_number":56,"context_line":"        path \u003d os.path.abspath(os.path.expanduser(path))"},{"line_number":57,"context_line":"        self._name_exists(name)"}],"source_content_type":"text/x-python","patch_set":23,"id":"7aa08908_fb5ee643","line":54,"in_reply_to":"9abb7d3a_d656df28","updated":"2016-06-06 15:30:27.000000000","message":"Correct, it\u0027s like rename but for paths.","commit_id":"dc9f756fda5d3a050927935da82e22cf0c711657"}],"tempest/tests/cmd/test_workspace.py":[{"author":{"_account_id":6167,"name":"Ken\u0027ichi Ohmichi","email":"ken1ohmichi@gmail.com","username":"oomichi"},"change_message_id":"cb676d304d0674c9dd0b167fec213cc10f597a73","unresolved":false,"context_lines":[{"line_number":14,"context_line":""},{"line_number":15,"context_line":"import subprocess"},{"line_number":16,"context_line":"import tempfile"},{"line_number":17,"context_line":"from uuid import uuid4"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"from tempest.cmd.workspace import WorkspaceManager"},{"line_number":20,"context_line":"from tempest.tests import base"}],"source_content_type":"text/x-python","patch_set":12,"id":"dab17558_c27d6b6e","line":17,"range":{"start_line":17,"start_character":0,"end_line":17,"end_character":22},"updated":"2016-05-17 07:33:39.000000000","message":"we can use the library rand_uuid() of data_utils module instead of uuid4().","commit_id":"0dc3aef6caa4f1482a79ec76bdbe6fbbcf8766cd"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"11b73449f04c9096196386d5503c3268b16b3563","unresolved":false,"context_lines":[{"line_number":87,"context_line":"        self.assertEqual(return_code, 0)"},{"line_number":88,"context_line":"        workspace_manager \u003d WorkspaceManager()"},{"line_number":89,"context_line":"        self.assertIsNotNone(workspace_manager.get_workspace(name))"},{"line_number":90,"context_line":"        self._remove_workspace(workspace_manager, name)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    def test_workspace_manager_update_name(self):"},{"line_number":93,"context_line":"        old_name \u003d data_utils.rand_uuid()"}],"source_content_type":"text/x-python","patch_set":13,"id":"bab6814e_b0bb1875","line":90,"range":{"start_line":90,"start_character":8,"end_line":90,"end_character":55},"updated":"2016-05-18 02:41:02.000000000","message":"No _remove_workspace() in this instance.","commit_id":"5478d6c19a5f11eb860f9ee202ef51d7aef1649f"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"4422553910e8f3a563d942daeb30d6ed657ca03f","unresolved":false,"context_lines":[{"line_number":87,"context_line":"        self.assertEqual(return_code, 0)"},{"line_number":88,"context_line":"        workspace_manager \u003d WorkspaceManager()"},{"line_number":89,"context_line":"        self.assertIsNotNone(workspace_manager.get_workspace(name))"},{"line_number":90,"context_line":"        self._remove_workspace(workspace_manager, name)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    def test_workspace_manager_update_name(self):"},{"line_number":93,"context_line":"        old_name \u003d data_utils.rand_uuid()"}],"source_content_type":"text/x-python","patch_set":13,"id":"bab6814e_53f9164d","line":90,"range":{"start_line":90,"start_character":8,"end_line":90,"end_character":55},"in_reply_to":"bab6814e_b0bb1875","updated":"2016-05-18 03:05:42.000000000","message":"Done","commit_id":"5478d6c19a5f11eb860f9ee202ef51d7aef1649f"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"11b73449f04c9096196386d5503c3268b16b3563","unresolved":false,"context_lines":[{"line_number":102,"context_line":"        workspace_manager \u003d WorkspaceManager()"},{"line_number":103,"context_line":"        self.assertIsNone(workspace_manager.get_workspace(old_name))"},{"line_number":104,"context_line":"        self.assertIsNotNone(workspace_manager.get_workspace(new_name))"},{"line_number":105,"context_line":"        self._remove_workspace(workspace_manager, new_name)"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    def test_workspace_manager_update_path(self):"},{"line_number":108,"context_line":"        name \u003d data_utils.rand_uuid()"}],"source_content_type":"text/x-python","patch_set":13,"id":"bab6814e_f0b5a07e","line":105,"range":{"start_line":105,"start_character":8,"end_line":105,"end_character":59},"updated":"2016-05-18 02:41:02.000000000","message":"ditto","commit_id":"5478d6c19a5f11eb860f9ee202ef51d7aef1649f"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"4422553910e8f3a563d942daeb30d6ed657ca03f","unresolved":false,"context_lines":[{"line_number":102,"context_line":"        workspace_manager \u003d WorkspaceManager()"},{"line_number":103,"context_line":"        self.assertIsNone(workspace_manager.get_workspace(old_name))"},{"line_number":104,"context_line":"        self.assertIsNotNone(workspace_manager.get_workspace(new_name))"},{"line_number":105,"context_line":"        self._remove_workspace(workspace_manager, new_name)"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    def test_workspace_manager_update_path(self):"},{"line_number":108,"context_line":"        name \u003d data_utils.rand_uuid()"}],"source_content_type":"text/x-python","patch_set":13,"id":"bab6814e_b394c2e8","line":105,"range":{"start_line":105,"start_character":8,"end_line":105,"end_character":59},"in_reply_to":"bab6814e_f0b5a07e","updated":"2016-05-18 03:05:42.000000000","message":"Done","commit_id":"5478d6c19a5f11eb860f9ee202ef51d7aef1649f"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"11b73449f04c9096196386d5503c3268b16b3563","unresolved":false,"context_lines":[{"line_number":117,"context_line":"        workspace_manager \u003d WorkspaceManager()"},{"line_number":118,"context_line":"        workspace \u003d workspace_manager.get_workspace(name)"},{"line_number":119,"context_line":"        self.assertEqual(workspace.get(\"path\"), new_path)"},{"line_number":120,"context_line":"        self._remove_workspace(workspace_manager, name)"}],"source_content_type":"text/x-python","patch_set":13,"id":"bab6814e_10adc431","line":120,"range":{"start_line":120,"start_character":8,"end_line":120,"end_character":55},"updated":"2016-05-18 02:41:02.000000000","message":"here","commit_id":"5478d6c19a5f11eb860f9ee202ef51d7aef1649f"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"4422553910e8f3a563d942daeb30d6ed657ca03f","unresolved":false,"context_lines":[{"line_number":117,"context_line":"        workspace_manager \u003d WorkspaceManager()"},{"line_number":118,"context_line":"        workspace \u003d workspace_manager.get_workspace(name)"},{"line_number":119,"context_line":"        self.assertEqual(workspace.get(\"path\"), new_path)"},{"line_number":120,"context_line":"        self._remove_workspace(workspace_manager, name)"}],"source_content_type":"text/x-python","patch_set":13,"id":"bab6814e_9399be22","line":120,"range":{"start_line":120,"start_character":8,"end_line":120,"end_character":55},"in_reply_to":"bab6814e_10adc431","updated":"2016-05-18 03:05:42.000000000","message":"Done","commit_id":"5478d6c19a5f11eb860f9ee202ef51d7aef1649f"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"51d4512ca85ca3d2b341c8c5c395f7b8e32fed21","unresolved":false,"context_lines":[{"line_number":27,"context_line":"        self.assertEqual(return_code, 0)"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def test_run_workspace_register(self):"},{"line_number":30,"context_line":"        name \u003d data_utils.rand_uuid()"},{"line_number":31,"context_line":"        path \u003d tempfile.mkdtemp()"},{"line_number":32,"context_line":"        return_code \u003d subprocess.call("},{"line_number":33,"context_line":"            [\u0027tempest\u0027, \u0027workspace\u0027, \u0027register\u0027, \u0027--name\u0027, name,"},{"line_number":34,"context_line":"             \u0027--path\u0027, path], stdout\u003dsubprocess.PIPE)"}],"source_content_type":"text/x-python","patch_set":24,"id":"7aa08908_5469abbd","line":31,"range":{"start_line":30,"start_character":8,"end_line":31,"end_character":33},"updated":"2016-06-07 04:20:50.000000000","message":"We can do this in setup() to save on the code duplication right?","commit_id":"db7d2685ed3f5b5afbacf5939b43fd1c01194ef6"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"51d4512ca85ca3d2b341c8c5c395f7b8e32fed21","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def test_run_workspace_register(self):"},{"line_number":30,"context_line":"        name \u003d data_utils.rand_uuid()"},{"line_number":31,"context_line":"        path \u003d tempfile.mkdtemp()"},{"line_number":32,"context_line":"        return_code \u003d subprocess.call("},{"line_number":33,"context_line":"            [\u0027tempest\u0027, \u0027workspace\u0027, \u0027register\u0027, \u0027--name\u0027, name,"},{"line_number":34,"context_line":"             \u0027--path\u0027, path], stdout\u003dsubprocess.PIPE)"}],"source_content_type":"text/x-python","patch_set":24,"id":"7aa08908_b4028f07","line":31,"updated":"2016-06-07 04:20:50.000000000","message":"We probably should add a safety addcleanup here and for every other test we\u0027re potentially leaking a tempdir for each test failure. Just something like:\n\n  self.addCleanup(shutil.rmtree, path ignore_errors\u003dTrue)\n\nshould ensure we never leak anything.","commit_id":"db7d2685ed3f5b5afbacf5939b43fd1c01194ef6"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"f3292eb6879a3c2a722e4ac329d55c4ea88d3bf7","unresolved":false,"context_lines":[{"line_number":27,"context_line":"        self.assertEqual(return_code, 0)"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def test_run_workspace_register(self):"},{"line_number":30,"context_line":"        name \u003d data_utils.rand_uuid()"},{"line_number":31,"context_line":"        path \u003d tempfile.mkdtemp()"},{"line_number":32,"context_line":"        return_code \u003d subprocess.call("},{"line_number":33,"context_line":"            [\u0027tempest\u0027, \u0027workspace\u0027, \u0027register\u0027, \u0027--name\u0027, name,"},{"line_number":34,"context_line":"             \u0027--path\u0027, path], stdout\u003dsubprocess.PIPE)"}],"source_content_type":"text/x-python","patch_set":24,"id":"7aa08908_b463af40","line":31,"range":{"start_line":30,"start_character":8,"end_line":31,"end_character":33},"in_reply_to":"7aa08908_5469abbd","updated":"2016-06-07 04:54:27.000000000","message":"Done","commit_id":"db7d2685ed3f5b5afbacf5939b43fd1c01194ef6"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"f3292eb6879a3c2a722e4ac329d55c4ea88d3bf7","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def test_run_workspace_register(self):"},{"line_number":30,"context_line":"        name \u003d data_utils.rand_uuid()"},{"line_number":31,"context_line":"        path \u003d tempfile.mkdtemp()"},{"line_number":32,"context_line":"        return_code \u003d subprocess.call("},{"line_number":33,"context_line":"            [\u0027tempest\u0027, \u0027workspace\u0027, \u0027register\u0027, \u0027--name\u0027, name,"},{"line_number":34,"context_line":"             \u0027--path\u0027, path], stdout\u003dsubprocess.PIPE)"}],"source_content_type":"text/x-python","patch_set":24,"id":"7aa08908_145ba388","line":31,"in_reply_to":"7aa08908_b4028f07","updated":"2016-06-07 04:54:27.000000000","message":"Done","commit_id":"db7d2685ed3f5b5afbacf5939b43fd1c01194ef6"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"51d4512ca85ca3d2b341c8c5c395f7b8e32fed21","unresolved":false,"context_lines":[{"line_number":86,"context_line":"    def test_workspace_manager_get(self):"},{"line_number":87,"context_line":"        name \u003d data_utils.rand_uuid()"},{"line_number":88,"context_line":"        path \u003d tempfile.mkdtemp()"},{"line_number":89,"context_line":"        return_code \u003d subprocess.call("},{"line_number":90,"context_line":"            [\u0027tempest\u0027, \u0027workspace\u0027, \u0027register\u0027, \u0027--name\u0027, name,"},{"line_number":91,"context_line":"             \u0027--path\u0027, path], stdout\u003dsubprocess.PIPE)"},{"line_number":92,"context_line":"        self.assertEqual(return_code, 0)"}],"source_content_type":"text/x-python","patch_set":24,"id":"7aa08908_d44d9b73","line":89,"updated":"2016-06-07 04:20:50.000000000","message":"Why are we calling subprocess here? I don\u0027t think we should shell out for strict unit tests of the the manager. Can\u0027t we just call workspace_manager.register_new_workspace() directly? The class seperation you\u0027ve got here looks like the other class is for CLI testing and this is for the python interface testing. I\u0027d rather see it cleanly separated if so.","commit_id":"db7d2685ed3f5b5afbacf5939b43fd1c01194ef6"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"f3292eb6879a3c2a722e4ac329d55c4ea88d3bf7","unresolved":false,"context_lines":[{"line_number":86,"context_line":"    def test_workspace_manager_get(self):"},{"line_number":87,"context_line":"        name \u003d data_utils.rand_uuid()"},{"line_number":88,"context_line":"        path \u003d tempfile.mkdtemp()"},{"line_number":89,"context_line":"        return_code \u003d subprocess.call("},{"line_number":90,"context_line":"            [\u0027tempest\u0027, \u0027workspace\u0027, \u0027register\u0027, \u0027--name\u0027, name,"},{"line_number":91,"context_line":"             \u0027--path\u0027, path], stdout\u003dsubprocess.PIPE)"},{"line_number":92,"context_line":"        self.assertEqual(return_code, 0)"}],"source_content_type":"text/x-python","patch_set":24,"id":"7aa08908_f45d377a","line":89,"in_reply_to":"7aa08908_d44d9b73","updated":"2016-06-07 04:54:27.000000000","message":"Done","commit_id":"db7d2685ed3f5b5afbacf5939b43fd1c01194ef6"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"51d4512ca85ca3d2b341c8c5c395f7b8e32fed21","unresolved":false,"context_lines":[{"line_number":110,"context_line":"        workspace_manager.remove_workspace(new_name)"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"    def test_workspace_manager_move(self):"},{"line_number":113,"context_line":"        name \u003d data_utils.rand_uuid()"},{"line_number":114,"context_line":"        old_path \u003d tempfile.mkdtemp()"},{"line_number":115,"context_line":"        new_path \u003d tempfile.mkdtemp()"},{"line_number":116,"context_line":"        return_code \u003d subprocess.call("},{"line_number":117,"context_line":"            [\u0027tempest\u0027, \u0027workspace\u0027, \u0027register\u0027, \u0027--name\u0027, name,"},{"line_number":118,"context_line":"             \u0027--path\u0027, old_path], stdout\u003dsubprocess.PIPE)"},{"line_number":119,"context_line":"        self.assertEqual(return_code, 0)"},{"line_number":120,"context_line":"        workspace_manager \u003d WorkspaceManager()"},{"line_number":121,"context_line":"        workspace_manager.move_workspace(name, new_path)"},{"line_number":122,"context_line":"        workspace_manager \u003d WorkspaceManager()"}],"source_content_type":"text/x-python","patch_set":24,"id":"7aa08908_d49bdbc7","line":119,"range":{"start_line":113,"start_character":8,"end_line":119,"end_character":40},"updated":"2016-06-07 04:20:50.000000000","message":"This can be in setup() right","commit_id":"db7d2685ed3f5b5afbacf5939b43fd1c01194ef6"},{"author":{"_account_id":9364,"name":"Stephen Lowrie","email":"stephen.lowrie@rackspace.com","username":"step6829"},"change_message_id":"f3292eb6879a3c2a722e4ac329d55c4ea88d3bf7","unresolved":false,"context_lines":[{"line_number":110,"context_line":"        workspace_manager.remove_workspace(new_name)"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"    def test_workspace_manager_move(self):"},{"line_number":113,"context_line":"        name \u003d data_utils.rand_uuid()"},{"line_number":114,"context_line":"        old_path \u003d tempfile.mkdtemp()"},{"line_number":115,"context_line":"        new_path \u003d tempfile.mkdtemp()"},{"line_number":116,"context_line":"        return_code \u003d subprocess.call("},{"line_number":117,"context_line":"            [\u0027tempest\u0027, \u0027workspace\u0027, \u0027register\u0027, \u0027--name\u0027, name,"},{"line_number":118,"context_line":"             \u0027--path\u0027, old_path], stdout\u003dsubprocess.PIPE)"},{"line_number":119,"context_line":"        self.assertEqual(return_code, 0)"},{"line_number":120,"context_line":"        workspace_manager \u003d WorkspaceManager()"},{"line_number":121,"context_line":"        workspace_manager.move_workspace(name, new_path)"},{"line_number":122,"context_line":"        workspace_manager \u003d WorkspaceManager()"}],"source_content_type":"text/x-python","patch_set":24,"id":"7aa08908_54552b4e","line":119,"range":{"start_line":113,"start_character":8,"end_line":119,"end_character":40},"in_reply_to":"7aa08908_d49bdbc7","updated":"2016-06-07 04:54:27.000000000","message":"Done","commit_id":"db7d2685ed3f5b5afbacf5939b43fd1c01194ef6"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"b504427ea26a7a369b372f0c9938d268e4333f37","unresolved":false,"context_lines":[{"line_number":31,"context_line":"        self.workspace_manager.register_new_workspace(self.name, self.path)"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    def test_run_workspace_list(self):"},{"line_number":34,"context_line":"        return_code \u003d subprocess.call("},{"line_number":35,"context_line":"            [\u0027tempest\u0027, \u0027workspace\u0027, \u0027list\u0027], stdout\u003dsubprocess.PIPE)"},{"line_number":36,"context_line":"        self.assertEqual(return_code, 0)"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    def test_run_workspace_register(self):"}],"source_content_type":"text/x-python","patch_set":26,"id":"7aa08908_20cdb55d","line":35,"range":{"start_line":34,"start_character":0,"end_line":35,"end_character":69},"updated":"2016-06-07 07:12:16.000000000","message":"I just found a document. I think this should be replaced with subprocess.popen() and communicate() according to the document.\n\n-------\nNote Do not use stdout\u003dPIPE or stderr\u003dPIPE with this function as that can deadlock based on the child process output volume. Use Popen with the communicate() method when you need pipes.\n-------\nhttps://docs.python.org/2/library/subprocess.html#subprocess.call","commit_id":"e05d6c3bb7138e0b5986e66e1469094aa9076282"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"bb5dda8ff41e38279fa4d48ea1b6b925997f9441","unresolved":false,"context_lines":[{"line_number":91,"context_line":"        os.mkdir(path)"},{"line_number":92,"context_line":"        self.addCleanup(shutil.rmtree, path, ignore_errors\u003dTrue)"},{"line_number":93,"context_line":"        process \u003d subprocess.Popen("},{"line_number":94,"context_line":"            [\u0027tempest\u0027, \u0027init\u0027, name], cwd\u003dpath,"},{"line_number":95,"context_line":"            stdout\u003dsubprocess.PIPE)"},{"line_number":96,"context_line":"        process.communicate()"},{"line_number":97,"context_line":"        return_code \u003d process.returncode"}],"source_content_type":"text/x-python","patch_set":31,"id":"7aa08908_38d770ee","line":94,"updated":"2016-06-08 01:51:26.000000000","message":"This is failing because the global conf dir is still being referenced by the sample config file generation:\n\nhttp://paste.openstack.org/show/508812/\n\nWe probably don\u0027t want to rely on tempest init here (if we can avoid it) since clearly something is weird about how things get installed here","commit_id":"a43e08372590f19ebffb4b0362370c92355ea38c"}]}
