)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":17776,"name":"Reedip","email":"reedip.banerjee@gmail.com","username":"Reedip"},"change_message_id":"5bd15b554be3f820349d9558bb809e7835efdcbd","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Class MultiKeyValueAction will be used to parse arguments like this:"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"    --route destination\u003dxxx,gateway\u003dxxx --route destination\u003dyyy,gateway\u003dyyy"},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"The result is a list like this:"},{"line_number":14,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":7,"id":"bae84128_7c404408","line":11,"updated":"2016-02-25 01:47:20.000000000","message":"Can you remove the extra space at the beginning, so that the commit message does not extend beyond the boundary ( Feels good to look at)","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"94e01fdaf7e1ced175efeadac278cabc6b5bd74d","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Class MultiKeyValueAction will be used to parse arguments like this:"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"    --route destination\u003dxxx,gateway\u003dxxx --route destination\u003dyyy,gateway\u003dyyy"},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"The result is a list like this:"},{"line_number":14,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":7,"id":"bae84128_0d646447","line":11,"in_reply_to":"bae84128_7c404408","updated":"2016-02-25 04:05:07.000000000","message":"Done","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"}],"openstackclient/common/parseractions.py":[{"author":{"_account_id":8410,"name":"Richard Theis","email":"rtheis@us.ibm.com","username":"rtheis"},"change_message_id":"48efab4465e44733872c23a330e3468873286d6e","unresolved":false,"context_lines":[{"line_number":54,"context_line":"            if \u0027\u003d\u0027 in kv:"},{"line_number":55,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"},{"line_number":56,"context_line":"            else:"},{"line_number":57,"context_line":"                msg \u003d (\"%s expected multiple key\u003dvalue pairs separated by \""},{"line_number":58,"context_line":"                       \"comma\" % (str(option_string)))"},{"line_number":59,"context_line":"                raise argparse.ArgumentTypeError(self, msg)"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"5a5ae5dd_b39f5fb3","line":57,"updated":"2016-02-04 16:31:23.000000000","message":"Does this method need to verify that multiple key\u003dvalue pairs are specified?  It appears that a single key\u003dvalue pair is sufficient.","commit_id":"3dc0778a289b0e7b3af233fd8aa71d60682ba497"},{"author":{"_account_id":8410,"name":"Richard Theis","email":"rtheis@us.ibm.com","username":"rtheis"},"change_message_id":"9679481b2e08f3544427ad64bc3ea5c3830be75c","unresolved":false,"context_lines":[{"line_number":54,"context_line":"            if \u0027\u003d\u0027 in kv:"},{"line_number":55,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"},{"line_number":56,"context_line":"            else:"},{"line_number":57,"context_line":"                msg \u003d (\"%s expected multiple key\u003dvalue pairs separated by \""},{"line_number":58,"context_line":"                       \"comma\" % (str(option_string)))"},{"line_number":59,"context_line":"                raise argparse.ArgumentTypeError(self, msg)"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"5a5ae5dd_4e02f570","line":57,"in_reply_to":"5a5ae5dd_4ecbde72","updated":"2016-02-04 20:06:27.000000000","message":"I wonder if it make sense to do something similar to https://review.openstack.org/#/c/253878/ where validation is done on the required and valid keys.","commit_id":"3dc0778a289b0e7b3af233fd8aa71d60682ba497"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"dad229da755416a38805a75cf394d884d277342a","unresolved":false,"context_lines":[{"line_number":54,"context_line":"            if \u0027\u003d\u0027 in kv:"},{"line_number":55,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"},{"line_number":56,"context_line":"            else:"},{"line_number":57,"context_line":"                msg \u003d (\"%s expected multiple key\u003dvalue pairs separated by \""},{"line_number":58,"context_line":"                       \"comma\" % (str(option_string)))"},{"line_number":59,"context_line":"                raise argparse.ArgumentTypeError(self, msg)"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"5a5ae5dd_4ecbde72","line":57,"in_reply_to":"5a5ae5dd_b39f5fb3","updated":"2016-02-04 16:49:39.000000000","message":"Oh, yes, I see. I miss understood your meaning last time, I think. Do you mean since this action expects multiple kv pairs, we need to verify it first ?","commit_id":"3dc0778a289b0e7b3af233fd8aa71d60682ba497"},{"author":{"_account_id":8410,"name":"Richard Theis","email":"rtheis@us.ibm.com","username":"rtheis"},"change_message_id":"48efab4465e44733872c23a330e3468873286d6e","unresolved":false,"context_lines":[{"line_number":55,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"},{"line_number":56,"context_line":"            else:"},{"line_number":57,"context_line":"                msg \u003d (\"%s expected multiple key\u003dvalue pairs separated by \""},{"line_number":58,"context_line":"                       \"comma\" % (str(option_string)))"},{"line_number":59,"context_line":"                raise argparse.ArgumentTypeError(self, msg)"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        # Append the dict to the dest list"}],"source_content_type":"text/x-python","patch_set":1,"id":"5a5ae5dd_9032590f","line":58,"updated":"2016-02-04 16:31:23.000000000","message":"It would be nice to include the key\u003dvalue pair that caused the error.","commit_id":"3dc0778a289b0e7b3af233fd8aa71d60682ba497"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"dad229da755416a38805a75cf394d884d277342a","unresolved":false,"context_lines":[{"line_number":55,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"},{"line_number":56,"context_line":"            else:"},{"line_number":57,"context_line":"                msg \u003d (\"%s expected multiple key\u003dvalue pairs separated by \""},{"line_number":58,"context_line":"                       \"comma\" % (str(option_string)))"},{"line_number":59,"context_line":"                raise argparse.ArgumentTypeError(self, msg)"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        # Append the dict to the dest list"}],"source_content_type":"text/x-python","patch_set":1,"id":"5a5ae5dd_eebf2af9","line":58,"in_reply_to":"5a5ae5dd_9032590f","updated":"2016-02-04 16:49:39.000000000","message":"Sorry I didn\u0027t reply your former comment. option_string will show the whole problematic option string.","commit_id":"3dc0778a289b0e7b3af233fd8aa71d60682ba497"},{"author":{"_account_id":8410,"name":"Richard Theis","email":"rtheis@us.ibm.com","username":"rtheis"},"change_message_id":"9679481b2e08f3544427ad64bc3ea5c3830be75c","unresolved":false,"context_lines":[{"line_number":55,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"},{"line_number":56,"context_line":"            else:"},{"line_number":57,"context_line":"                msg \u003d (\"%s expected multiple key\u003dvalue pairs separated by \""},{"line_number":58,"context_line":"                       \"comma\" % (str(option_string)))"},{"line_number":59,"context_line":"                raise argparse.ArgumentTypeError(self, msg)"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        # Append the dict to the dest list"}],"source_content_type":"text/x-python","patch_set":1,"id":"5a5ae5dd_932fbaf5","line":58,"in_reply_to":"5a5ae5dd_eebf2af9","updated":"2016-02-04 20:06:27.000000000","message":"While this helps some, it doesn\u0027t identify the specific key\u003dvalue pair that failed to be parsed.","commit_id":"3dc0778a289b0e7b3af233fd8aa71d60682ba497"},{"author":{"_account_id":8410,"name":"Richard Theis","email":"rtheis@us.ibm.com","username":"rtheis"},"change_message_id":"ddce30da5241c7ea7df66ab42503737e73861295","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    dicts, with key\u003dvalue pairs in them."},{"line_number":44,"context_line":"    \"\"\""},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    def __call__(self, parser, namespace, values, option_string\u003dNone):"},{"line_number":47,"context_line":"        # Make sure we have an empty list rather than None"},{"line_number":48,"context_line":"        if getattr(namespace, self.dest, None) is None:"},{"line_number":49,"context_line":"            setattr(namespace, self.dest, [])"}],"source_content_type":"text/x-python","patch_set":3,"id":"dae33548_d91a697c","line":46,"updated":"2016-02-18 17:48:49.000000000","message":"Should we do something similar to https://review.openstack.org/#/c/253878/ where validation is done on the required and valid keys?","commit_id":"ad738d519e59ea495fe1a2d0830845562c8d9425"},{"author":{"_account_id":8410,"name":"Richard Theis","email":"rtheis@us.ibm.com","username":"rtheis"},"change_message_id":"8f3be1c9e4cf34efd99e24811dc896c5a007c31c","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    dicts, with key\u003dvalue pairs in them."},{"line_number":44,"context_line":"    \"\"\""},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    def __call__(self, parser, namespace, values, option_string\u003dNone):"},{"line_number":47,"context_line":"        # Make sure we have an empty list rather than None"},{"line_number":48,"context_line":"        if getattr(namespace, self.dest, None) is None:"},{"line_number":49,"context_line":"            setattr(namespace, self.dest, [])"}],"source_content_type":"text/x-python","patch_set":3,"id":"dae33548_7ce4e6aa","line":46,"in_reply_to":"dae33548_d91a697c","updated":"2016-02-18 19:44:35.000000000","message":"We discuss this during today\u0027s meeting.  Please see http://eavesdrop.openstack.org/meetings/openstackclient/2016/openstackclient.2016-02-18-19.11.log.html for details.","commit_id":"ad738d519e59ea495fe1a2d0830845562c8d9425"},{"author":{"_account_id":970,"name":"Dean Troyer","email":"dtroyer@gmail.com","username":"dtroyer"},"change_message_id":"c60376512238e56674e834712d62e781852b1870","unresolved":false,"context_lines":[{"line_number":51,"context_line":"                             % nargs)"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"        super(MultiKeyValueAction, self).__init__(option_strings, dest)"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        # required_keys: A list of keys that is required. None by default."},{"line_number":56,"context_line":"        self.required_keys \u003d kwargs.get(\u0027required_keys\u0027)"},{"line_number":57,"context_line":"        if self.required_keys and not isinstance(self.required_keys, list):"}],"source_content_type":"text/x-python","patch_set":5,"id":"bae84128_9ab2fa04","line":54,"updated":"2016-02-22 23:23:18.000000000","message":"The two keys below should be keyword args so they can be properly documented.","commit_id":"8f1ba154470e347be3976d49a5efb24fefe0c515"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"f21114ff26f7cccba5d6764dde49e523df0f00e5","unresolved":false,"context_lines":[{"line_number":51,"context_line":"                             % nargs)"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"        super(MultiKeyValueAction, self).__init__(option_strings, dest)"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        # required_keys: A list of keys that is required. None by default."},{"line_number":56,"context_line":"        self.required_keys \u003d kwargs.get(\u0027required_keys\u0027)"},{"line_number":57,"context_line":"        if self.required_keys and not isinstance(self.required_keys, list):"}],"source_content_type":"text/x-python","patch_set":5,"id":"bae84128_bb952734","line":54,"in_reply_to":"bae84128_9ab2fa04","updated":"2016-02-23 12:40:20.000000000","message":"Done","commit_id":"8f1ba154470e347be3976d49a5efb24fefe0c515"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"a2f801a58191f31882216179a0c91bc855a02af3","unresolved":false,"context_lines":[{"line_number":51,"context_line":"                             % nargs)"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"        super(MultiKeyValueAction, self).__init__(option_strings, dest)"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        # required_keys: A list of keys that is required. None by default."},{"line_number":56,"context_line":"        self.required_keys \u003d kwargs.get(\u0027required_keys\u0027)"},{"line_number":57,"context_line":"        if self.required_keys and not isinstance(self.required_keys, list):"}],"source_content_type":"text/x-python","patch_set":5,"id":"bae84128_090adf89","line":54,"in_reply_to":"bae84128_9ab2fa04","updated":"2016-02-24 06:47:46.000000000","message":"Hi Dean,\n\nBut I think they are already kwargs. I just expected them to be parsed from kwargs. Do I misunderstand you ?","commit_id":"8f1ba154470e347be3976d49a5efb24fefe0c515"},{"author":{"_account_id":970,"name":"Dean Troyer","email":"dtroyer@gmail.com","username":"dtroyer"},"change_message_id":"c60376512238e56674e834712d62e781852b1870","unresolved":false,"context_lines":[{"line_number":68,"context_line":"            setattr(namespace, self.dest, [])"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        tmpdict \u003d {}"},{"line_number":71,"context_line":"        for kv in values.split(\u0027,\u0027):"},{"line_number":72,"context_line":"            # Add value if an assignment else remove it"},{"line_number":73,"context_line":"            if \u0027\u003d\u0027 in kv:"},{"line_number":74,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"}],"source_content_type":"text/x-python","patch_set":5,"id":"bae84128_4d76fea4","line":71,"updated":"2016-02-22 23:23:18.000000000","message":"We should note maybe that a comma may not be used inside a value, ever.","commit_id":"8f1ba154470e347be3976d49a5efb24fefe0c515"},{"author":{"_account_id":8410,"name":"Richard Theis","email":"rtheis@us.ibm.com","username":"rtheis"},"change_message_id":"44b664e0ce04e9163c21e0fadc0048321b495819","unresolved":false,"context_lines":[{"line_number":68,"context_line":"            setattr(namespace, self.dest, [])"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        tmpdict \u003d {}"},{"line_number":71,"context_line":"        for kv in values.split(\u0027,\u0027):"},{"line_number":72,"context_line":"            # Add value if an assignment else remove it"},{"line_number":73,"context_line":"            if \u0027\u003d\u0027 in kv:"},{"line_number":74,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"}],"source_content_type":"text/x-python","patch_set":5,"id":"bae84128_42b96e2d","line":71,"in_reply_to":"bae84128_262e37a5","updated":"2016-02-23 22:31:51.000000000","message":"I don\u0027t think that the separator needs to be a parameter at this time.  It could be added in the future.  The documentation for this method could note that the separator (comma) may not be used inside a value.","commit_id":"8f1ba154470e347be3976d49a5efb24fefe0c515"},{"author":{"_account_id":970,"name":"Dean Troyer","email":"dtroyer@gmail.com","username":"dtroyer"},"change_message_id":"d97ab8067a1dd9de889c06738d5a1193731aeb27","unresolved":false,"context_lines":[{"line_number":68,"context_line":"            setattr(namespace, self.dest, [])"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        tmpdict \u003d {}"},{"line_number":71,"context_line":"        for kv in values.split(\u0027,\u0027):"},{"line_number":72,"context_line":"            # Add value if an assignment else remove it"},{"line_number":73,"context_line":"            if \u0027\u003d\u0027 in kv:"},{"line_number":74,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"}],"source_content_type":"text/x-python","patch_set":5,"id":"bae84128_8ff1de6d","line":71,"in_reply_to":"bae84128_262e37a5","updated":"2016-02-23 23:38:50.000000000","message":"Not a parameter, no matter what the separator is, it may not be used in a value because no quoting is supported with a plain .split() call.\n\nI don\u0027t expect that to be a problem, but it should be noted.","commit_id":"8f1ba154470e347be3976d49a5efb24fefe0c515"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"f21114ff26f7cccba5d6764dde49e523df0f00e5","unresolved":false,"context_lines":[{"line_number":68,"context_line":"            setattr(namespace, self.dest, [])"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        tmpdict \u003d {}"},{"line_number":71,"context_line":"        for kv in values.split(\u0027,\u0027):"},{"line_number":72,"context_line":"            # Add value if an assignment else remove it"},{"line_number":73,"context_line":"            if \u0027\u003d\u0027 in kv:"},{"line_number":74,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"}],"source_content_type":"text/x-python","patch_set":5,"id":"bae84128_262e37a5","line":71,"in_reply_to":"bae84128_4d76fea4","updated":"2016-02-23 12:40:20.000000000","message":"Do you mean the separator should be a parameter ?","commit_id":"8f1ba154470e347be3976d49a5efb24fefe0c515"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"a2f801a58191f31882216179a0c91bc855a02af3","unresolved":false,"context_lines":[{"line_number":68,"context_line":"            setattr(namespace, self.dest, [])"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        tmpdict \u003d {}"},{"line_number":71,"context_line":"        for kv in values.split(\u0027,\u0027):"},{"line_number":72,"context_line":"            # Add value if an assignment else remove it"},{"line_number":73,"context_line":"            if \u0027\u003d\u0027 in kv:"},{"line_number":74,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"}],"source_content_type":"text/x-python","patch_set":5,"id":"bae84128_09e3ffd9","line":71,"in_reply_to":"bae84128_8ff1de6d","updated":"2016-02-24 06:47:46.000000000","message":"Hi Dean, Richard,\n\nOK, I see. Will doc it.","commit_id":"8f1ba154470e347be3976d49a5efb24fefe0c515"},{"author":{"_account_id":8410,"name":"Richard Theis","email":"rtheis@us.ibm.com","username":"rtheis"},"change_message_id":"d335b1eb49e2319a041a6b5c3c94f8be25aa6533","unresolved":false,"context_lines":[{"line_number":45,"context_line":"    dicts, with key\u003dvalue pairs in them."},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    NOTE: The arguments string should be a comma separated key-value pairs."},{"line_number":48,"context_line":"    And the comma should never be used in the key or value."},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def __init__(self, option_strings, dest, nargs\u003dNone, **kwargs):"}],"source_content_type":"text/x-python","patch_set":6,"id":"bae84128_df041016","line":48,"updated":"2016-02-24 13:19:07.000000000","message":"An equal shouldn\u0027t be used either.","commit_id":"a18b5b4d282b6ec582b0c590e63ef6dff41ec89d"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"4ec1110dae08b4e85fe93359cd395e9588516d67","unresolved":false,"context_lines":[{"line_number":45,"context_line":"    dicts, with key\u003dvalue pairs in them."},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    NOTE: The arguments string should be a comma separated key-value pairs."},{"line_number":48,"context_line":"    And the comma should never be used in the key or value."},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def __init__(self, option_strings, dest, nargs\u003dNone, **kwargs):"}],"source_content_type":"text/x-python","patch_set":6,"id":"bae84128_c761bed5","line":48,"in_reply_to":"bae84128_df041016","updated":"2016-02-25 00:50:47.000000000","message":"Done","commit_id":"a18b5b4d282b6ec582b0c590e63ef6dff41ec89d"},{"author":{"_account_id":8410,"name":"Richard Theis","email":"rtheis@us.ibm.com","username":"rtheis"},"change_message_id":"d335b1eb49e2319a041a6b5c3c94f8be25aa6533","unresolved":false,"context_lines":[{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        :param kwargs: customized options. Available options could be:"},{"line_number":55,"context_line":"           required_keys: a list of required keys"},{"line_number":56,"context_line":"           optional_keys: a lsit of optional keys"},{"line_number":57,"context_line":"        \"\"\""},{"line_number":58,"context_line":"        if nargs is not None:"},{"line_number":59,"context_line":"            raise ValueError(\"Parameter \u0027nargs\u0027 is not allowed, but got %s\""}],"source_content_type":"text/x-python","patch_set":6,"id":"bae84128_4452f767","line":56,"updated":"2016-02-24 13:19:07.000000000","message":"nit...type on \u0027lsit\u0027","commit_id":"a18b5b4d282b6ec582b0c590e63ef6dff41ec89d"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"4ec1110dae08b4e85fe93359cd395e9588516d67","unresolved":false,"context_lines":[{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        :param kwargs: customized options. Available options could be:"},{"line_number":55,"context_line":"           required_keys: a list of required keys"},{"line_number":56,"context_line":"           optional_keys: a lsit of optional keys"},{"line_number":57,"context_line":"        \"\"\""},{"line_number":58,"context_line":"        if nargs is not None:"},{"line_number":59,"context_line":"            raise ValueError(\"Parameter \u0027nargs\u0027 is not allowed, but got %s\""}],"source_content_type":"text/x-python","patch_set":6,"id":"bae84128_8767b6e9","line":56,"in_reply_to":"bae84128_4452f767","updated":"2016-02-25 00:50:47.000000000","message":"Done","commit_id":"a18b5b4d282b6ec582b0c590e63ef6dff41ec89d"},{"author":{"_account_id":8410,"name":"Richard Theis","email":"rtheis@us.ibm.com","username":"rtheis"},"change_message_id":"d335b1eb49e2319a041a6b5c3c94f8be25aa6533","unresolved":false,"context_lines":[{"line_number":107,"context_line":"            missing_keys \u003d [k for k in self.required_keys if k not in tmpdict]"},{"line_number":108,"context_line":"            if missing_keys:"},{"line_number":109,"context_line":"                msg \u003d _(\"Missing required keys %(missing_keys)s.\\n\""},{"line_number":110,"context_line":"                        \"ALl vaild keys are: %(all_keys)s.\")"},{"line_number":111,"context_line":"                raise argparse.ArgumentTypeError("},{"line_number":112,"context_line":"                    msg % {\u0027missing_keys\u0027: \u0027, \u0027.join(missing_keys),"},{"line_number":113,"context_line":"                           \u0027all_keys\u0027: \u0027, \u0027.join(all_keys)}"}],"source_content_type":"text/x-python","patch_set":6,"id":"bae84128_04b8ef73","line":110,"updated":"2016-02-24 13:19:07.000000000","message":"Typo in message ... \"ALl\" should be \"All\".","commit_id":"a18b5b4d282b6ec582b0c590e63ef6dff41ec89d"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"4ec1110dae08b4e85fe93359cd395e9588516d67","unresolved":false,"context_lines":[{"line_number":107,"context_line":"            missing_keys \u003d [k for k in self.required_keys if k not in tmpdict]"},{"line_number":108,"context_line":"            if missing_keys:"},{"line_number":109,"context_line":"                msg \u003d _(\"Missing required keys %(missing_keys)s.\\n\""},{"line_number":110,"context_line":"                        \"ALl vaild keys are: %(all_keys)s.\")"},{"line_number":111,"context_line":"                raise argparse.ArgumentTypeError("},{"line_number":112,"context_line":"                    msg % {\u0027missing_keys\u0027: \u0027, \u0027.join(missing_keys),"},{"line_number":113,"context_line":"                           \u0027all_keys\u0027: \u0027, \u0027.join(all_keys)}"}],"source_content_type":"text/x-python","patch_set":6,"id":"bae84128_27722aae","line":110,"in_reply_to":"bae84128_04b8ef73","updated":"2016-02-25 00:50:47.000000000","message":"Done","commit_id":"a18b5b4d282b6ec582b0c590e63ef6dff41ec89d"},{"author":{"_account_id":17776,"name":"Reedip","email":"reedip.banerjee@gmail.com","username":"Reedip"},"change_message_id":"5bd15b554be3f820349d9558bb809e7835efdcbd","unresolved":false,"context_lines":[{"line_number":45,"context_line":"    dicts, with key\u003dvalue pairs in them."},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    NOTE: The arguments string should be a comma separated key-value pairs."},{"line_number":48,"context_line":"    And comma(\u0027,\u0027) and equal(\u0027\u003d\u0027) should never be used in the key or value."},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def __init__(self, option_strings, dest, nargs\u003dNone, **kwargs):"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_d9736214","line":48,"updated":"2016-02-25 01:47:20.000000000","message":"Is the note important here in the code, or should such things be moved to devref?","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"94e01fdaf7e1ced175efeadac278cabc6b5bd74d","unresolved":false,"context_lines":[{"line_number":45,"context_line":"    dicts, with key\u003dvalue pairs in them."},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    NOTE: The arguments string should be a comma separated key-value pairs."},{"line_number":48,"context_line":"    And comma(\u0027,\u0027) and equal(\u0027\u003d\u0027) should never be used in the key or value."},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def __init__(self, option_strings, dest, nargs\u003dNone, **kwargs):"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_68e7deac","line":48,"in_reply_to":"bae84128_d9736214","updated":"2016-02-25 04:05:07.000000000","message":"Please just keep it here. I love docs in code. :)","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":17776,"name":"Reedip","email":"reedip.banerjee@gmail.com","username":"Reedip"},"change_message_id":"5bd15b554be3f820349d9558bb809e7835efdcbd","unresolved":false,"context_lines":[{"line_number":55,"context_line":"           required_keys: a list of required keys"},{"line_number":56,"context_line":"           optional_keys: a list of optional keys"},{"line_number":57,"context_line":"        \"\"\""},{"line_number":58,"context_line":"        if nargs is not None:"},{"line_number":59,"context_line":"            raise ValueError(\"Parameter \u0027nargs\u0027 is not allowed, but got %s\""},{"line_number":60,"context_line":"                             % nargs)"},{"line_number":61,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_19994a20","line":58,"updated":"2016-02-25 01:47:20.000000000","message":"If we are assuming nargs to always be a String ( as per Line#59-60), then I think you can do\n\n if nargs:\n\nInstead of checking it for None","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"94e01fdaf7e1ced175efeadac278cabc6b5bd74d","unresolved":false,"context_lines":[{"line_number":55,"context_line":"           required_keys: a list of required keys"},{"line_number":56,"context_line":"           optional_keys: a list of optional keys"},{"line_number":57,"context_line":"        \"\"\""},{"line_number":58,"context_line":"        if nargs is not None:"},{"line_number":59,"context_line":"            raise ValueError(\"Parameter \u0027nargs\u0027 is not allowed, but got %s\""},{"line_number":60,"context_line":"                             % nargs)"},{"line_number":61,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_285f9676","line":58,"in_reply_to":"bae84128_19994a20","updated":"2016-02-25 04:05:07.000000000","message":"Done","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":17776,"name":"Reedip","email":"reedip.banerjee@gmail.com","username":"Reedip"},"change_message_id":"5bd15b554be3f820349d9558bb809e7835efdcbd","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        super(MultiKeyValueAction, self).__init__(option_strings, dest)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"        # required_keys: A list of keys that is required. None by default."},{"line_number":65,"context_line":"        self.required_keys \u003d kwargs.get(\u0027required_keys\u0027)"},{"line_number":66,"context_line":"        if self.required_keys and not isinstance(self.required_keys, list):"},{"line_number":67,"context_line":"            raise TypeError(\"\u0027required_keys\u0027 should be a list\")"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_b9765ed6","line":65,"updated":"2016-02-25 01:47:20.000000000","message":"You can take required_keys and optional keys to a single function, and pass to it the attribute required_keys/optional_keys , if you want to remove the duplicated code( just a suggestion, looks good other wise as it only removes duplication once)","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"94e01fdaf7e1ced175efeadac278cabc6b5bd74d","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        super(MultiKeyValueAction, self).__init__(option_strings, dest)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"        # required_keys: A list of keys that is required. None by default."},{"line_number":65,"context_line":"        self.required_keys \u003d kwargs.get(\u0027required_keys\u0027)"},{"line_number":66,"context_line":"        if self.required_keys and not isinstance(self.required_keys, list):"},{"line_number":67,"context_line":"            raise TypeError(\"\u0027required_keys\u0027 should be a list\")"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_c8738a14","line":65,"in_reply_to":"bae84128_b9765ed6","updated":"2016-02-25 04:05:07.000000000","message":"If there is more code like this, I think we can use a common helper for this. :)","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":17776,"name":"Reedip","email":"reedip.banerjee@gmail.com","username":"Reedip"},"change_message_id":"5bd15b554be3f820349d9558bb809e7835efdcbd","unresolved":false,"context_lines":[{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def __call__(self, parser, namespace, values, metavar\u003dNone):"},{"line_number":75,"context_line":"        # Make sure we have an empty list rather than None"},{"line_number":76,"context_line":"        if getattr(namespace, self.dest, None) is None:"},{"line_number":77,"context_line":"            setattr(namespace, self.dest, [])"},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"        tmpdict \u003d {}"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_5c2460ae","line":76,"updated":"2016-02-25 01:47:20.000000000","message":"assuming that self.dest is defined, and we are checking for namespace.self.dest, can we do this ??\n\n namespace.self.dest \u003d namespace.self.dest or []\n\nThis basically sets namespace.self.dest to [] if it is None ( just a thought)","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"94e01fdaf7e1ced175efeadac278cabc6b5bd74d","unresolved":false,"context_lines":[{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def __call__(self, parser, namespace, values, metavar\u003dNone):"},{"line_number":75,"context_line":"        # Make sure we have an empty list rather than None"},{"line_number":76,"context_line":"        if getattr(namespace, self.dest, None) is None:"},{"line_number":77,"context_line":"            setattr(namespace, self.dest, [])"},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"        tmpdict \u003d {}"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_e89e4e62","line":76,"in_reply_to":"bae84128_5c2460ae","updated":"2016-02-25 04:05:07.000000000","message":"I\u0027d like to use getattr() and setattr() instead. :)","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":17776,"name":"Reedip","email":"reedip.banerjee@gmail.com","username":"Reedip"},"change_message_id":"5bd15b554be3f820349d9558bb809e7835efdcbd","unresolved":false,"context_lines":[{"line_number":97,"context_line":"            invalid_keys \u003d [k for k in tmpdict if k not in all_keys]"},{"line_number":98,"context_line":"            if invalid_keys:"},{"line_number":99,"context_line":"                msg \u003d _(\"Invalid keys %(invalid_keys)s specified.\\n\""},{"line_number":100,"context_line":"                        \"All valid keys are: %(all_keys)s.\")"},{"line_number":101,"context_line":"                raise argparse.ArgumentTypeError("},{"line_number":102,"context_line":"                    msg % {\u0027invalid_keys\u0027: \u0027, \u0027.join(invalid_keys),"},{"line_number":103,"context_line":"                           \u0027all_keys\u0027: \u0027, \u0027.join(all_keys)}"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_9cab88d6","line":100,"range":{"start_line":100,"start_character":25,"end_line":100,"end_character":28},"updated":"2016-02-25 01:47:20.000000000","message":"Do we need All here? \nWe can simply write \"Valid keys are ....\"","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"94e01fdaf7e1ced175efeadac278cabc6b5bd74d","unresolved":false,"context_lines":[{"line_number":97,"context_line":"            invalid_keys \u003d [k for k in tmpdict if k not in all_keys]"},{"line_number":98,"context_line":"            if invalid_keys:"},{"line_number":99,"context_line":"                msg \u003d _(\"Invalid keys %(invalid_keys)s specified.\\n\""},{"line_number":100,"context_line":"                        \"All valid keys are: %(all_keys)s.\")"},{"line_number":101,"context_line":"                raise argparse.ArgumentTypeError("},{"line_number":102,"context_line":"                    msg % {\u0027invalid_keys\u0027: \u0027, \u0027.join(invalid_keys),"},{"line_number":103,"context_line":"                           \u0027all_keys\u0027: \u0027, \u0027.join(all_keys)}"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_8d8514af","line":100,"range":{"start_line":100,"start_character":25,"end_line":100,"end_character":28},"in_reply_to":"bae84128_9cab88d6","updated":"2016-02-25 04:05:07.000000000","message":"Done","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":17776,"name":"Reedip","email":"reedip.banerjee@gmail.com","username":"Reedip"},"change_message_id":"5bd15b554be3f820349d9558bb809e7835efdcbd","unresolved":false,"context_lines":[{"line_number":107,"context_line":"            missing_keys \u003d [k for k in self.required_keys if k not in tmpdict]"},{"line_number":108,"context_line":"            if missing_keys:"},{"line_number":109,"context_line":"                msg \u003d _(\"Missing required keys %(missing_keys)s.\\n\""},{"line_number":110,"context_line":"                        \"All vaild keys are: %(all_keys)s.\")"},{"line_number":111,"context_line":"                raise argparse.ArgumentTypeError("},{"line_number":112,"context_line":"                    msg % {\u0027missing_keys\u0027: \u0027, \u0027.join(missing_keys),"},{"line_number":113,"context_line":"                           \u0027all_keys\u0027: \u0027, \u0027.join(all_keys)}"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_fc8f3473","line":110,"updated":"2016-02-25 01:47:20.000000000","message":"ditto","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"94e01fdaf7e1ced175efeadac278cabc6b5bd74d","unresolved":false,"context_lines":[{"line_number":107,"context_line":"            missing_keys \u003d [k for k in self.required_keys if k not in tmpdict]"},{"line_number":108,"context_line":"            if missing_keys:"},{"line_number":109,"context_line":"                msg \u003d _(\"Missing required keys %(missing_keys)s.\\n\""},{"line_number":110,"context_line":"                        \"All vaild keys are: %(all_keys)s.\")"},{"line_number":111,"context_line":"                raise argparse.ArgumentTypeError("},{"line_number":112,"context_line":"                    msg % {\u0027missing_keys\u0027: \u0027, \u0027.join(missing_keys),"},{"line_number":113,"context_line":"                           \u0027all_keys\u0027: \u0027, \u0027.join(all_keys)}"}],"source_content_type":"text/x-python","patch_set":7,"id":"bae84128_cd8f1ccb","line":110,"in_reply_to":"bae84128_fc8f3473","updated":"2016-02-25 04:05:07.000000000","message":"Done","commit_id":"6a08255af1cfd0865962af8812dff339c3b1fc69"},{"author":{"_account_id":970,"name":"Dean Troyer","email":"dtroyer@gmail.com","username":"dtroyer"},"change_message_id":"2c2060c46aeb3d7f12c259d5aa9c64df6dcda8a4","unresolved":false,"context_lines":[{"line_number":45,"context_line":"    dicts, with key\u003dvalue pairs in them."},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    NOTE: The arguments string should be a comma separated key-value pairs."},{"line_number":48,"context_line":"    And comma(\u0027,\u0027) and equal(\u0027\u003d\u0027) should never be used in the key or value."},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def __init__(self, option_strings, dest, nargs\u003dNone, **kwargs):"}],"source_content_type":"text/x-python","patch_set":8,"id":"9aed3d3a_e5a972e1","line":48,"updated":"2016-02-25 17:27:22.000000000","message":"s/should never be used/may not be used/","commit_id":"8670c629352b53a097b31fa6a6e6227945da8938"},{"author":{"_account_id":970,"name":"Dean Troyer","email":"dtroyer@gmail.com","username":"dtroyer"},"change_message_id":"2c2060c46aeb3d7f12c259d5aa9c64df6dcda8a4","unresolved":false,"context_lines":[{"line_number":48,"context_line":"    And comma(\u0027,\u0027) and equal(\u0027\u003d\u0027) should never be used in the key or value."},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def __init__(self, option_strings, dest, nargs\u003dNone, **kwargs):"},{"line_number":52,"context_line":"        \"\"\"Initialize the action object, and parse customized options"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        :param kwargs: customized options. Available options could be:"}],"source_content_type":"text/x-python","patch_set":8,"id":"9aed3d3a_a2992022","line":51,"updated":"2016-02-25 17:27:22.000000000","message":"I think it is clearer, especially in generalized lib functions like this, to explicitly list the args that will be acted upon here.  Then you can also add them to the docstring as regular arguments.\n\nIt would also allow you to pass kwargs to the parent method and have your new arguments filtered out.","commit_id":"8670c629352b53a097b31fa6a6e6227945da8938"},{"author":{"_account_id":970,"name":"Dean Troyer","email":"dtroyer@gmail.com","username":"dtroyer"},"change_message_id":"2c2060c46aeb3d7f12c259d5aa9c64df6dcda8a4","unresolved":false,"context_lines":[{"line_number":59,"context_line":"            raise ValueError(\"Parameter \u0027nargs\u0027 is not allowed, but got %s\""},{"line_number":60,"context_line":"                             % nargs)"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        super(MultiKeyValueAction, self).__init__(option_strings, dest)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"        # required_keys: A list of keys that is required. None by default."},{"line_number":65,"context_line":"        self.required_keys \u003d kwargs.get(\u0027required_keys\u0027)"}],"source_content_type":"text/x-python","patch_set":8,"id":"9aed3d3a_8534e6de","line":62,"updated":"2016-02-25 17:27:22.000000000","message":"Should kwargs be included here?  There are a number of other options that should be passed up.","commit_id":"8670c629352b53a097b31fa6a6e6227945da8938"},{"author":{"_account_id":970,"name":"Dean Troyer","email":"dtroyer@gmail.com","username":"dtroyer"},"change_message_id":"2c2060c46aeb3d7f12c259d5aa9c64df6dcda8a4","unresolved":false,"context_lines":[{"line_number":64,"context_line":"        # required_keys: A list of keys that is required. None by default."},{"line_number":65,"context_line":"        self.required_keys \u003d kwargs.get(\u0027required_keys\u0027)"},{"line_number":66,"context_line":"        if self.required_keys and not isinstance(self.required_keys, list):"},{"line_number":67,"context_line":"            raise TypeError(\"\u0027required_keys\u0027 should be a list\")"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"        # optional_keys: A list of keys that is optional. None by default."},{"line_number":70,"context_line":"        self.optional_keys \u003d kwargs.get(\u0027optional_keys\u0027)"}],"source_content_type":"text/x-python","patch_set":8,"id":"9aed3d3a_a5300aa0","line":67,"updated":"2016-02-25 17:27:22.000000000","message":"s/should be/must be/","commit_id":"8670c629352b53a097b31fa6a6e6227945da8938"},{"author":{"_account_id":970,"name":"Dean Troyer","email":"dtroyer@gmail.com","username":"dtroyer"},"change_message_id":"2c2060c46aeb3d7f12c259d5aa9c64df6dcda8a4","unresolved":false,"context_lines":[{"line_number":69,"context_line":"        # optional_keys: A list of keys that is optional. None by default."},{"line_number":70,"context_line":"        self.optional_keys \u003d kwargs.get(\u0027optional_keys\u0027)"},{"line_number":71,"context_line":"        if self.optional_keys and not isinstance(self.optional_keys, list):"},{"line_number":72,"context_line":"            raise TypeError(\"\u0027optional_keys\u0027 should be a list\")"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def __call__(self, parser, namespace, values, metavar\u003dNone):"},{"line_number":75,"context_line":"        # Make sure we have an empty list rather than None"}],"source_content_type":"text/x-python","patch_set":8,"id":"9aed3d3a_05261668","line":72,"updated":"2016-02-25 17:27:22.000000000","message":"s/should be/must be/","commit_id":"8670c629352b53a097b31fa6a6e6227945da8938"},{"author":{"_account_id":970,"name":"Dean Troyer","email":"dtroyer@gmail.com","username":"dtroyer"},"change_message_id":"2c2060c46aeb3d7f12c259d5aa9c64df6dcda8a4","unresolved":false,"context_lines":[{"line_number":78,"context_line":""},{"line_number":79,"context_line":"        tmpdict \u003d {}"},{"line_number":80,"context_line":"        for kv in values.split(\u0027,\u0027):"},{"line_number":81,"context_line":"            # Add value if an assignment else remove it"},{"line_number":82,"context_line":"            if \u0027\u003d\u0027 in kv:"},{"line_number":83,"context_line":"                tmpdict.update([kv.split(\u0027\u003d\u0027, 1)])"},{"line_number":84,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":8,"id":"9aed3d3a_4572de7d","line":81,"updated":"2016-02-25 17:27:22.000000000","message":"... else raise TypeError","commit_id":"8670c629352b53a097b31fa6a6e6227945da8938"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"a15338bd93407081755b07a5c852602588d3c6fb","unresolved":false,"context_lines":[{"line_number":53,"context_line":"        \"\"\"Initialize the action object, and parse customized options"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        :param required_keys: a list of required keys"},{"line_number":56,"context_line":"        :param optional_keys: a list of optional keys"},{"line_number":57,"context_line":"        \"\"\""},{"line_number":58,"context_line":"        if nargs:"},{"line_number":59,"context_line":"            raise ValueError(\"Parameter \u0027nargs\u0027 is not allowed, but got %s\""}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_5d6ef396","line":56,"updated":"2016-02-26 15:02:18.000000000","message":"It is better to explain when key validation is done.\nIf both of required_keys and optional_keys are not specified, key validation will be skipped.","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"145cde7a75351050c64b29b72a909eb2b58ef3f9","unresolved":false,"context_lines":[{"line_number":53,"context_line":"        \"\"\"Initialize the action object, and parse customized options"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        :param required_keys: a list of required keys"},{"line_number":56,"context_line":"        :param optional_keys: a list of optional keys"},{"line_number":57,"context_line":"        \"\"\""},{"line_number":58,"context_line":"        if nargs:"},{"line_number":59,"context_line":"            raise ValueError(\"Parameter \u0027nargs\u0027 is not allowed, but got %s\""}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_036fdcc5","line":56,"in_reply_to":"9aed3d3a_5d6ef396","updated":"2016-02-26 20:44:11.000000000","message":"Done","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"a15338bd93407081755b07a5c852602588d3c6fb","unresolved":false,"context_lines":[{"line_number":63,"context_line":"                                                  dest, **kwargs)"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        # required_keys: A list of keys that is required. None by default."},{"line_number":66,"context_line":"        self.required_keys \u003d required_keys"},{"line_number":67,"context_line":"        if self.required_keys and not isinstance(self.required_keys, list):"},{"line_number":68,"context_line":"            raise TypeError(\"\u0027required_keys\u0027 must be a list\")"},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_9db51b33","line":66,"range":{"start_line":66,"start_character":8,"end_line":66,"end_character":42},"updated":"2016-02-26 15:02:18.000000000","message":"I think it is better to convert required_keys from a list to set.\nIt will simplify the code of __call__.","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"145cde7a75351050c64b29b72a909eb2b58ef3f9","unresolved":false,"context_lines":[{"line_number":63,"context_line":"                                                  dest, **kwargs)"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        # required_keys: A list of keys that is required. None by default."},{"line_number":66,"context_line":"        self.required_keys \u003d required_keys"},{"line_number":67,"context_line":"        if self.required_keys and not isinstance(self.required_keys, list):"},{"line_number":68,"context_line":"            raise TypeError(\"\u0027required_keys\u0027 must be a list\")"},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_c3c7b410","line":66,"range":{"start_line":66,"start_character":8,"end_line":66,"end_character":42},"in_reply_to":"9aed3d3a_9db51b33","updated":"2016-02-26 20:44:11.000000000","message":"Done","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"a15338bd93407081755b07a5c852602588d3c6fb","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        if getattr(namespace, self.dest, None) is None:"},{"line_number":78,"context_line":"            setattr(namespace, self.dest, [])"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"        tmpdict \u003d {}"},{"line_number":81,"context_line":"        for kv in values.split(\u0027,\u0027):"},{"line_number":82,"context_line":"            # Add value if an assignment else raise ArgumentTypeError"},{"line_number":83,"context_line":"            if \u0027\u003d\u0027 in kv:"}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_fdff07ff","line":80,"range":{"start_line":80,"start_character":8,"end_line":80,"end_character":15},"updated":"2016-02-26 15:02:18.000000000","message":"tmpdir sounds too temporary name.\nHow about specified_params or similar one.","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"145cde7a75351050c64b29b72a909eb2b58ef3f9","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        if getattr(namespace, self.dest, None) is None:"},{"line_number":78,"context_line":"            setattr(namespace, self.dest, [])"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"        tmpdict \u003d {}"},{"line_number":81,"context_line":"        for kv in values.split(\u0027,\u0027):"},{"line_number":82,"context_line":"            # Add value if an assignment else raise ArgumentTypeError"},{"line_number":83,"context_line":"            if \u0027\u003d\u0027 in kv:"}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_63f8684a","line":80,"range":{"start_line":80,"start_character":8,"end_line":80,"end_character":15},"in_reply_to":"9aed3d3a_fdff07ff","updated":"2016-02-26 20:44:11.000000000","message":"Let\u0027s name it \"params\". :)","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"a15338bd93407081755b07a5c852602588d3c6fb","unresolved":false,"context_lines":[{"line_number":88,"context_line":"                raise argparse.ArgumentTypeError(self, msg)"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"        # Check key validation"},{"line_number":91,"context_line":"        all_keys \u003d []"},{"line_number":92,"context_line":"        if self.required_keys:"},{"line_number":93,"context_line":"            all_keys +\u003d self.required_keys"},{"line_number":94,"context_line":"        if self.optional_keys:"},{"line_number":95,"context_line":"            all_keys +\u003d self.optional_keys"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"        if all_keys:"},{"line_number":98,"context_line":"            invalid_keys \u003d [k for k in tmpdict if k not in all_keys]"}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_1ad591b8","line":95,"range":{"start_line":91,"start_character":8,"end_line":95,"end_character":42},"updated":"2016-02-26 15:02:18.000000000","message":"I think it is better to use \u0027set\u0027.\n\n  valid_keys \u003d set(self.required_keys or []) | set(self.optional_keys or [])\n\nIn addition, \u0027valid_keys\u0027 is more meaningful than all_keys.\n\nInstead of using \u0027or []\u0027, you can ensure required/optional_keys are [] in __init__.","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"145cde7a75351050c64b29b72a909eb2b58ef3f9","unresolved":false,"context_lines":[{"line_number":88,"context_line":"                raise argparse.ArgumentTypeError(self, msg)"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"        # Check key validation"},{"line_number":91,"context_line":"        all_keys \u003d []"},{"line_number":92,"context_line":"        if self.required_keys:"},{"line_number":93,"context_line":"            all_keys +\u003d self.required_keys"},{"line_number":94,"context_line":"        if self.optional_keys:"},{"line_number":95,"context_line":"            all_keys +\u003d self.optional_keys"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"        if all_keys:"},{"line_number":98,"context_line":"            invalid_keys \u003d [k for k in tmpdict if k not in all_keys]"}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_de0ca73d","line":95,"range":{"start_line":91,"start_character":8,"end_line":95,"end_character":42},"in_reply_to":"9aed3d3a_1ad591b8","updated":"2016-02-26 20:44:11.000000000","message":"Done","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"}],"openstackclient/tests/common/test_parseractions.py":[{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"a15338bd93407081755b07a5c852602588d3c6fb","unresolved":false,"context_lines":[{"line_number":69,"context_line":"        self.parser \u003d argparse.ArgumentParser()"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"        # Set up our typical usage"},{"line_number":72,"context_line":"        self.parser.add_argument("},{"line_number":73,"context_line":"            \u0027--route\u0027,"},{"line_number":74,"context_line":"            metavar\u003d\u0027dest\u003dxxx,gateway\u003dyyy\u0027,"},{"line_number":75,"context_line":"            action\u003dparseractions.MultiKeyValueAction,"},{"line_number":76,"context_line":"            dest\u003d\u0027routes\u0027,"},{"line_number":77,"context_line":"            default\u003dNone,"}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_1d9d8b59","line":74,"range":{"start_line":72,"start_character":11,"end_line":74,"end_character":43},"updated":"2016-02-26 15:02:18.000000000","message":"How about \u0027--test\u0027 instead of \u0027--route\u0027?","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"145cde7a75351050c64b29b72a909eb2b58ef3f9","unresolved":false,"context_lines":[{"line_number":69,"context_line":"        self.parser \u003d argparse.ArgumentParser()"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"        # Set up our typical usage"},{"line_number":72,"context_line":"        self.parser.add_argument("},{"line_number":73,"context_line":"            \u0027--route\u0027,"},{"line_number":74,"context_line":"            metavar\u003d\u0027dest\u003dxxx,gateway\u003dyyy\u0027,"},{"line_number":75,"context_line":"            action\u003dparseractions.MultiKeyValueAction,"},{"line_number":76,"context_line":"            dest\u003d\u0027routes\u0027,"},{"line_number":77,"context_line":"            default\u003dNone,"}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_98bd17da","line":74,"range":{"start_line":72,"start_character":11,"end_line":74,"end_character":43},"in_reply_to":"9aed3d3a_1d9d8b59","updated":"2016-02-26 20:44:11.000000000","message":"Done","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"a15338bd93407081755b07a5c852602588d3c6fb","unresolved":false,"context_lines":[{"line_number":75,"context_line":"            action\u003dparseractions.MultiKeyValueAction,"},{"line_number":76,"context_line":"            dest\u003d\u0027routes\u0027,"},{"line_number":77,"context_line":"            default\u003dNone,"},{"line_number":78,"context_line":"            required_keys\u003d[\u0027dest\u0027, \u0027gateway\u0027],"},{"line_number":79,"context_line":"            optional_keys\u003d[\u0027option1\u0027, \u0027option2\u0027],"},{"line_number":80,"context_line":"            help\u003d\u0027Route associated with this router \u0027"},{"line_number":81,"context_line":"                 \u0027(repeat option to set multiple routes)\u0027,"}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_bdc9ff7a","line":78,"range":{"start_line":78,"start_character":12,"end_line":78,"end_character":46},"updated":"2016-02-26 15:02:18.000000000","message":"I don\u0027t think we need to use names with meaning like:\n\n  required_keys\u003d[\u0027req1\u0027, \u0027req2\u0027]","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"},{"author":{"_account_id":14937,"name":"Tang Chen","email":"imtangchen@163.com","username":"tangchen"},"change_message_id":"145cde7a75351050c64b29b72a909eb2b58ef3f9","unresolved":false,"context_lines":[{"line_number":75,"context_line":"            action\u003dparseractions.MultiKeyValueAction,"},{"line_number":76,"context_line":"            dest\u003d\u0027routes\u0027,"},{"line_number":77,"context_line":"            default\u003dNone,"},{"line_number":78,"context_line":"            required_keys\u003d[\u0027dest\u0027, \u0027gateway\u0027],"},{"line_number":79,"context_line":"            optional_keys\u003d[\u0027option1\u0027, \u0027option2\u0027],"},{"line_number":80,"context_line":"            help\u003d\u0027Route associated with this router \u0027"},{"line_number":81,"context_line":"                 \u0027(repeat option to set multiple routes)\u0027,"}],"source_content_type":"text/x-python","patch_set":9,"id":"9aed3d3a_d8b79ff3","line":78,"range":{"start_line":78,"start_character":12,"end_line":78,"end_character":46},"in_reply_to":"9aed3d3a_bdc9ff7a","updated":"2016-02-26 20:44:11.000000000","message":"Done","commit_id":"140328a5273088315c11fca5d9c7b9a421166c17"}]}
