From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35273) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ykxir-0004fd-Fk for qemu-devel@nongnu.org; Wed, 22 Apr 2015 12:42:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Ykxih-0006lf-VQ for qemu-devel@nongnu.org; Wed, 22 Apr 2015 12:42:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:35691) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ykxih-0006l6-N3 for qemu-devel@nongnu.org; Wed, 22 Apr 2015 12:41:51 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id 597028E717 for ; Wed, 22 Apr 2015 16:41:51 +0000 (UTC) Message-ID: <5537CF4E.9030707@redhat.com> Date: Wed, 22 Apr 2015 12:41:50 -0400 From: John Snow MIME-Version: 1.0 References: <1429719709-880-1-git-send-email-jsnow@redhat.com> <1429719709-880-3-git-send-email-jsnow@redhat.com> In-Reply-To: <1429719709-880-3-git-send-email-jsnow@redhat.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v2 2/4] scripts: qmp-shell: Expand support for QMP expressions List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kchamart@redhat.com, lcapitulino@redhat.com On 04/22/2015 12:21 PM, John Snow wrote: > This includes support for [] expressions, single-quotes in > QMP expressions (which is not strictly a part of JSON), and > the ability to use "True" or "False" literals instead of > JSON's lowercased 'true' and 'false' literals. > > qmp-shell currently allows you to describe values as > JSON expressions: > key={"key":{"key2":"val"}} > > But it does not currently support arrays, which are needed > for serializing and deserializing transactions: > key=[{"type":"drive-backup","data":{...}}] > > qmp-shell also only currently accepts doubly quoted strings > as-per JSON spec, but QMP allows single quotes. > > Lastly, python allows you to utilize "True" or "False" as > boolean literals, but JSON expects "true" or "false". Expand > qmp-shell to allow the user to type either, converting to the > correct type. > > As a consequence of the above, the key=val parsing is also improved > to give better error messages if a key=val token is not provided. > > CAVEAT: The parser is still extremely rudimentary and does not > expect to find spaces in {} nor [] expressions. This patch does > not improve this functionality. > > Signed-off-by: John Snow > --- > scripts/qmp/qmp-shell | 44 ++++++++++++++++++++++++++++---------------- > 1 file changed, 28 insertions(+), 16 deletions(-) > Left a line dangling in my local tree by accident: diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell index 4cdcb6c..e7b40eb 100755 --- a/scripts/qmp/qmp-shell +++ b/scripts/qmp/qmp-shell @@ -32,6 +32,7 @@ import qmp import json +import ast import readline import sys import pprint > diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell > index a9632ec..4cdcb6c 100755 > --- a/scripts/qmp/qmp-shell > +++ b/scripts/qmp/qmp-shell > @@ -88,23 +88,35 @@ class QMPShell(qmp.QEMUMonitorProtocol): > # clearing everything as it doesn't seem to matter > readline.set_completer_delims('') > > + def __parse_value(self, val): > + try: > + return int(val) > + except ValueError: > + pass > + > + if val.lower() == 'true': > + return True > + if val.lower() == 'false': > + return False > + if val.startswith(('{', '[')): > + try: > + return json.loads(val) > + except ValueError: > + pass > + try: > + return ast.literal_eval(val) > + except SyntaxError: > + pass > + return val > + > def __cli_expr(self, tokens, parent): > for arg in tokens: > - opt = arg.split('=') > - try: > - if(len(opt) > 2): > - opt[1] = '='.join(opt[1:]) > - value = int(opt[1]) > - except ValueError: > - if opt[1] == 'true': > - value = True > - elif opt[1] == 'false': > - value = False > - elif opt[1].startswith('{'): > - value = json.loads(opt[1]) > - else: > - value = opt[1] > - optpath = opt[0].split('.') > + (key, _, val) = arg.partition('=') > + if not val: > + raise QMPShellError("Expected a key=value pair, got '%s'" % arg) > + > + value = __parse_value(val) > + optpath = key.split('.') > curpath = [] > for p in optpath[:-1]: > curpath.append(p) > @@ -117,7 +129,7 @@ class QMPShell(qmp.QEMUMonitorProtocol): > if type(parent[optpath[-1]]) is dict: > raise QMPShellError('Cannot use "%s" as both leaf and non-leaf key' % '.'.join(curpath)) > else: > - raise QMPShellError('Cannot set "%s" multiple times' % opt[0]) > + raise QMPShellError('Cannot set "%s" multiple times' % key) > parent[optpath[-1]] = value > > def __build_cmd(self, cmdline): >