* [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators @ 2023-09-11 11:13 Victor Toso 2023-09-11 11:13 ` [PATCH v2 11/11] qapi: scripts: add a generator for qapi's examples Victor Toso 2023-09-11 11:26 ` [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators Victor Toso 0 siblings, 2 replies; 4+ messages in thread From: Victor Toso @ 2023-09-11 11:13 UTC (permalink / raw) To: qemu-devel; +Cc: Markus Armbruster, John Snow, Daniel P . Berrangé The next patch adds a generator that also validates qapi documentation. We don't want to execute it with a test schema. Signed-off-by: Victor Toso <victortoso@redhat.com> --- scripts/qapi/main.py | 4 ++++ tests/meson.build | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/qapi/main.py b/scripts/qapi/main.py index 316736b6a2..7efdcc6b8d 100644 --- a/scripts/qapi/main.py +++ b/scripts/qapi/main.py @@ -33,6 +33,7 @@ def generate(schema_file: str, prefix: str, unmask: bool = False, builtins: bool = False, + test_schema: bool = False, gen_tracing: bool = False) -> None: """ Generate C code for the given schema into the target directory. @@ -75,6 +76,8 @@ def main() -> int: parser.add_argument('-u', '--unmask-non-abi-names', action='store_true', dest='unmask', help="expose non-ABI names in introspection") + parser.add_argument('-t', '--tests', action='store_true', + help="flag generator that is running with a test schema") # Option --suppress-tracing exists so we can avoid solving build system # problems. TODO Drop it when we no longer need it. @@ -96,6 +99,7 @@ def main() -> int: prefix=args.prefix, unmask=args.unmask, builtins=args.builtins, + test_schema=args.tests, gen_tracing=not args.suppress_tracing) except QAPIError as err: print(err, file=sys.stderr) diff --git a/tests/meson.build b/tests/meson.build index debaa4505e..ed0844a6a0 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -43,7 +43,7 @@ test_qapi_files = custom_target('Test QAPI files', 'qapi-schema/include/sub-module.json', 'qapi-schema/sub-sub-module.json'), command: [ qapi_gen, '-o', meson.current_build_dir(), - '-b', '-p', 'test-', '@INPUT0@', + '-t', '-b', '-p', 'test-', '@INPUT0@', '--suppress-tracing' ], depend_files: qapi_gen_depends) -- 2.41.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 11/11] qapi: scripts: add a generator for qapi's examples 2023-09-11 11:13 [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators Victor Toso @ 2023-09-11 11:13 ` Victor Toso 2023-09-11 11:26 ` [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators Victor Toso 1 sibling, 0 replies; 4+ messages in thread From: Victor Toso @ 2023-09-11 11:13 UTC (permalink / raw) To: qemu-devel; +Cc: Markus Armbruster, John Snow, Daniel P . Berrangé This generator has two goals: 1. Mechanical validation of QAPI examples 2. Generate the examples in a JSON format to be consumed for extra validation. The generator iterates over every Example section, parsing both server and client messages. The generator prints any inconsistency found, for example: | Error: Extra data: line 1 column 39 (char 38) | Location: cancel-vcpu-dirty-limit at qapi/migration.json:2017 | Data: {"execute": "cancel-vcpu-dirty-limit"}, | "arguments": { "cpu-index": 1 } } The generator will output other JSON file with all the examples in the QAPI module that they came from. This can be used to validate the introspection between QAPI/QMP to language bindings, for example: | { "examples": [ | { | "id": "ksuxwzfayw", | "client": [ | { | "sequence-order": 1 | "message-type": "command", | "message": | { "arguments": | { "device": "scratch", "size": 1073741824 }, | "execute": "block_resize" | }, | } ], | "server": [ | { | "sequence-order": 2 | "message-type": "return", | "message": { "return": {} }, | } ] | } | ] } Note that the order matters, as read by the Example section and translated into "sequence-order". A language binding project can then consume this files to Marshal and Unmarshal, comparing if the results are what is to be expected. RFC discussion: https://lists.gnu.org/archive/html/qemu-devel/2022-08/msg04641.html Signed-off-by: Victor Toso <victortoso@redhat.com> --- scripts/qapi/dumpexamples.py | 204 +++++++++++++++++++++++++++++++++++ scripts/qapi/main.py | 5 +- 2 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 scripts/qapi/dumpexamples.py diff --git a/scripts/qapi/dumpexamples.py b/scripts/qapi/dumpexamples.py new file mode 100644 index 0000000000..5a1c275bc8 --- /dev/null +++ b/scripts/qapi/dumpexamples.py @@ -0,0 +1,204 @@ +""" +Dump examples for Developers +""" +# Copyright (c) 2023 Red Hat Inc. +# +# Authors: +# Victor Toso <victortoso@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2. +# See the COPYING file in the top-level directory. + +# Just for type hint on self +from __future__ import annotations + +import os +import json +import random +import string + +from typing import Dict, List, Optional + +from .schema import ( + QAPISchema, + QAPISchemaType, + QAPISchemaVisitor, + QAPISchemaEnumMember, + QAPISchemaFeature, + QAPISchemaIfCond, + QAPISchemaObjectType, + QAPISchemaObjectTypeMember, + QAPISchemaVariants, +) +from .source import QAPISourceInfo + + +def gen_examples(schema: QAPISchema, + output_dir: str, + prefix: str) -> None: + vis = QAPISchemaGenExamplesVisitor(prefix) + schema.visit(vis) + vis.write(output_dir) + + +def get_id(random, size: int) -> str: + letters = string.ascii_lowercase + return ''.join(random.choice(letters) for i in range(size)) + + +def next_object(text, start, end, context) -> (Dict, bool): + # Start of json object + start = text.find("{", start) + end = text.rfind("}", start, end+1) + + # try catch, pretty print issues + try: + ret = json.loads(text[start:end+1]) + except Exception as e: + print("Error: {}\nLocation: {}\nData: {}\n".format( + str(e), context, text[start:end+1])) + return {}, True + else: + return ret, False + + +def parse_text_to_dicts(text: str, context: str) -> (List[Dict], bool): + examples, clients, servers = [], [], [] + failed = False + + count = 1 + c, s = text.find("->"), text.find("<-") + while c != -1 or s != -1: + if c == -1 or (s != -1 and s < c): + start, target = s, servers + else: + start, target = c, clients + + # Find the client and server, if any + if c != -1: + c = text.find("->", start + 1) + if s != -1: + s = text.find("<-", start + 1) + + # Find the limit of current's object. + # We first look for the next message, either client or server. If none + # is avaible, we set the end of the text as limit. + if c == -1 and s != -1: + end = s + elif c != -1 and s == -1: + end = c + elif c != -1 and s != -1: + end = (c < s) and c or s + else: + end = len(text) - 1 + + message, error = next_object(text, start, end, context) + if error: + failed = True + + if len(message) > 0: + message_type = "return" + if "execute" in message: + message_type = "command" + elif "event" in message: + message_type = "event" + + target.append({ + "sequence-order": count, + "message-type": message_type, + "message": message + }) + count += 1 + + examples.append({"client": clients, "server": servers}) + return examples, failed + + +def parse_examples_of(self: QAPISchemaGenExamplesVisitor, + name: str): + + assert(name in self.schema._entity_dict) + obj = self.schema._entity_dict[name] + assert((obj.doc is not None)) + module_name = obj._module.name + + # We initialize random with the name so that we get consistent example + # ids over different generations. The ids of a given example might + # change when adding/removing examples, but that's acceptable as the + # goal is just to grep $id to find what example failed at a given test + # with minimum chorn over regenerating. + random.seed(name, version=2) + + for s in obj.doc.sections: + if s.name != "Example": + continue + + if module_name not in self.target: + self.target[module_name] = [] + + context = f'''{name} at {obj.info.fname}:{obj.info.line}''' + examples, failed = parse_text_to_dicts(s.text, context) + if failed: + # To warn user that docs needs fixing + self.failed = True + + for example in examples: + self.target[module_name].append({ + "id": get_id(random, 10), + "client": example["client"], + "server": example["server"] + }) + + +class QAPISchemaGenExamplesVisitor(QAPISchemaVisitor): + + def __init__(self, prefix: str): + super().__init__() + self.target = {} + self.schema = None + self.failed = False + + def visit_begin(self, schema): + self.schema = schema + + def visit_end(self): + self.schema = None + assert not self.failed, "Should fix the docs" + + def write(self: QAPISchemaGenExamplesVisitor, + output_dir: str) -> None: + for filename, content in self.target.items(): + pathname = os.path.join(output_dir, "examples", filename) + odir = os.path.dirname(pathname) + os.makedirs(odir, exist_ok=True) + result = {"examples": content} + + with open(pathname, "w") as outfile: + outfile.write(json.dumps(result, indent=2, sort_keys=True)) + + def visit_command(self: QAPISchemaGenExamplesVisitor, + name: str, + info: Optional[QAPISourceInfo], + ifcond: QAPISchemaIfCond, + features: List[QAPISchemaFeature], + arg_type: Optional[QAPISchemaObjectType], + ret_type: Optional[QAPISchemaType], + gen: bool, + success_response: bool, + boxed: bool, + allow_oob: bool, + allow_preconfig: bool, + coroutine: bool) -> None: + + if gen: + parse_examples_of(self, name) + + def visit_event(self: QAPISchemaGenExamplesVisitor, + name: str, + info: Optional[QAPISourceInfo], + ifcond: QAPISchemaIfCond, + features: List[QAPISchemaFeature], + arg_type: Optional[QAPISchemaObjectType], + boxed: bool): + + parse_examples_of(self, name) diff --git a/scripts/qapi/main.py b/scripts/qapi/main.py index 7efdcc6b8d..9d71d78b55 100644 --- a/scripts/qapi/main.py +++ b/scripts/qapi/main.py @@ -13,6 +13,7 @@ from .commands import gen_commands from .common import must_match +from .dumpexamples import gen_examples from .error import QAPIError from .events import gen_events from .introspect import gen_introspect @@ -54,7 +55,9 @@ def generate(schema_file: str, gen_commands(schema, output_dir, prefix, gen_tracing) gen_events(schema, output_dir, prefix) gen_introspect(schema, output_dir, prefix, unmask) - + + if not test_schema: + gen_examples(schema, output_dir, prefix) def main() -> int: """ -- 2.41.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators 2023-09-11 11:13 [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators Victor Toso 2023-09-11 11:13 ` [PATCH v2 11/11] qapi: scripts: add a generator for qapi's examples Victor Toso @ 2023-09-11 11:26 ` Victor Toso 1 sibling, 0 replies; 4+ messages in thread From: Victor Toso @ 2023-09-11 11:26 UTC (permalink / raw) To: qemu-devel; +Cc: Markus Armbruster, John Snow, Daniel P . Berrangé [-- Attachment #1: Type: text/plain, Size: 2857 bytes --] Hi, Sorry, this two are part of v2, did a mistake with git-send-email. I'll add them to the right thread with --in-reply-to shortly (without cc, to avoid spamming people's inbox) v2: https://lists.gnu.org/archive/html/qemu-devel/2023-09/msg02383.html Cheers, Victor On Mon, Sep 11, 2023 at 01:13:23PM +0200, Victor Toso wrote: > The next patch adds a generator that also validates qapi > documentation. We don't want to execute it with a test schema. > > Signed-off-by: Victor Toso <victortoso@redhat.com> > --- > scripts/qapi/main.py | 4 ++++ > tests/meson.build | 2 +- > 2 files changed, 5 insertions(+), 1 deletion(-) > > diff --git a/scripts/qapi/main.py b/scripts/qapi/main.py > index 316736b6a2..7efdcc6b8d 100644 > --- a/scripts/qapi/main.py > +++ b/scripts/qapi/main.py > @@ -33,6 +33,7 @@ def generate(schema_file: str, > prefix: str, > unmask: bool = False, > builtins: bool = False, > + test_schema: bool = False, > gen_tracing: bool = False) -> None: > """ > Generate C code for the given schema into the target directory. > @@ -75,6 +76,8 @@ def main() -> int: > parser.add_argument('-u', '--unmask-non-abi-names', action='store_true', > dest='unmask', > help="expose non-ABI names in introspection") > + parser.add_argument('-t', '--tests', action='store_true', > + help="flag generator that is running with a test schema") > > # Option --suppress-tracing exists so we can avoid solving build system > # problems. TODO Drop it when we no longer need it. > @@ -96,6 +99,7 @@ def main() -> int: > prefix=args.prefix, > unmask=args.unmask, > builtins=args.builtins, > + test_schema=args.tests, > gen_tracing=not args.suppress_tracing) > except QAPIError as err: > print(err, file=sys.stderr) > diff --git a/tests/meson.build b/tests/meson.build > index debaa4505e..ed0844a6a0 100644 > --- a/tests/meson.build > +++ b/tests/meson.build > @@ -43,7 +43,7 @@ test_qapi_files = custom_target('Test QAPI files', > 'qapi-schema/include/sub-module.json', > 'qapi-schema/sub-sub-module.json'), > command: [ qapi_gen, '-o', meson.current_build_dir(), > - '-b', '-p', 'test-', '@INPUT0@', > + '-t', '-b', '-p', 'test-', '@INPUT0@', > '--suppress-tracing' ], > depend_files: qapi_gen_depends) > > -- > 2.41.0 > > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 00/11] Validate and test qapi examples @ 2023-09-11 10:40 Victor Toso 2023-09-11 11:27 ` [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators Victor Toso 0 siblings, 1 reply; 4+ messages in thread From: Victor Toso @ 2023-09-11 10:40 UTC (permalink / raw) To: qemu-devel; +Cc: Markus Armbruster, John Snow, Daniel P . Berrangé Hi, v1: https://lists.gnu.org/archive/html/qemu-devel/2023-09/msg00853.html Changes: - Fixed running the generator with tests (Daniel). Added a flag for the generator, set in tests/meson.build (Philippe). - Moved the script to the end of the series, to avoid git bisect issues (Daniel) - Added a proper assert() to the generator, making it fail if any documentation error was found instead of just printing to the stderr and carry on. (Daniel) - Fixed the 3 other warnings the generator was showing, we are 100% free of warnings (in my machine) Cheers, Victor Victor Toso (11): qapi: fix example of get-win32-socket command qapi: fix example of dumpdtb command qapi: fix example of cancel-vcpu-dirty-limit command qapi: fix example of set-vcpu-dirty-limit command qapi: fix example of calc-dirty-rate command qapi: fix example of NETDEV_STREAM_CONNECTED event qapi: fix example of query-rocker-of-dpa-flows command qapi: fix example of query-spice command qapi: fix example of query-blockstats command qapi: meson: add test flag to allow skip generators qapi: scripts: add a generator for qapi's examples qapi/block-core.json | 32 +++--- qapi/machine.json | 2 +- qapi/migration.json | 6 +- qapi/misc.json | 2 +- qapi/net.json | 6 +- qapi/rocker.json | 3 +- qapi/ui.json | 3 +- scripts/qapi/dumpexamples.py | 204 +++++++++++++++++++++++++++++++++++ scripts/qapi/main.py | 9 +- tests/meson.build | 2 +- 10 files changed, 239 insertions(+), 30 deletions(-) create mode 100644 scripts/qapi/dumpexamples.py -- 2.41.0 ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators 2023-09-11 10:40 [PATCH v2 00/11] Validate and test qapi examples Victor Toso @ 2023-09-11 11:27 ` Victor Toso 2023-09-11 11:27 ` [PATCH v2 11/11] qapi: scripts: add a generator for qapi's examples Victor Toso 0 siblings, 1 reply; 4+ messages in thread From: Victor Toso @ 2023-09-11 11:27 UTC (permalink / raw) To: qemu-devel The next patch adds a generator that also validates qapi documentation. We don't want to execute it with a test schema. Signed-off-by: Victor Toso <victortoso@redhat.com> --- scripts/qapi/main.py | 4 ++++ tests/meson.build | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/qapi/main.py b/scripts/qapi/main.py index 316736b6a2..7efdcc6b8d 100644 --- a/scripts/qapi/main.py +++ b/scripts/qapi/main.py @@ -33,6 +33,7 @@ def generate(schema_file: str, prefix: str, unmask: bool = False, builtins: bool = False, + test_schema: bool = False, gen_tracing: bool = False) -> None: """ Generate C code for the given schema into the target directory. @@ -75,6 +76,8 @@ def main() -> int: parser.add_argument('-u', '--unmask-non-abi-names', action='store_true', dest='unmask', help="expose non-ABI names in introspection") + parser.add_argument('-t', '--tests', action='store_true', + help="flag generator that is running with a test schema") # Option --suppress-tracing exists so we can avoid solving build system # problems. TODO Drop it when we no longer need it. @@ -96,6 +99,7 @@ def main() -> int: prefix=args.prefix, unmask=args.unmask, builtins=args.builtins, + test_schema=args.tests, gen_tracing=not args.suppress_tracing) except QAPIError as err: print(err, file=sys.stderr) diff --git a/tests/meson.build b/tests/meson.build index debaa4505e..ed0844a6a0 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -43,7 +43,7 @@ test_qapi_files = custom_target('Test QAPI files', 'qapi-schema/include/sub-module.json', 'qapi-schema/sub-sub-module.json'), command: [ qapi_gen, '-o', meson.current_build_dir(), - '-b', '-p', 'test-', '@INPUT0@', + '-t', '-b', '-p', 'test-', '@INPUT0@', '--suppress-tracing' ], depend_files: qapi_gen_depends) -- 2.41.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 11/11] qapi: scripts: add a generator for qapi's examples 2023-09-11 11:27 ` [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators Victor Toso @ 2023-09-11 11:27 ` Victor Toso 0 siblings, 0 replies; 4+ messages in thread From: Victor Toso @ 2023-09-11 11:27 UTC (permalink / raw) To: qemu-devel This generator has two goals: 1. Mechanical validation of QAPI examples 2. Generate the examples in a JSON format to be consumed for extra validation. The generator iterates over every Example section, parsing both server and client messages. The generator prints any inconsistency found, for example: | Error: Extra data: line 1 column 39 (char 38) | Location: cancel-vcpu-dirty-limit at qapi/migration.json:2017 | Data: {"execute": "cancel-vcpu-dirty-limit"}, | "arguments": { "cpu-index": 1 } } The generator will output other JSON file with all the examples in the QAPI module that they came from. This can be used to validate the introspection between QAPI/QMP to language bindings, for example: | { "examples": [ | { | "id": "ksuxwzfayw", | "client": [ | { | "sequence-order": 1 | "message-type": "command", | "message": | { "arguments": | { "device": "scratch", "size": 1073741824 }, | "execute": "block_resize" | }, | } ], | "server": [ | { | "sequence-order": 2 | "message-type": "return", | "message": { "return": {} }, | } ] | } | ] } Note that the order matters, as read by the Example section and translated into "sequence-order". A language binding project can then consume this files to Marshal and Unmarshal, comparing if the results are what is to be expected. RFC discussion: https://lists.gnu.org/archive/html/qemu-devel/2022-08/msg04641.html Signed-off-by: Victor Toso <victortoso@redhat.com> --- scripts/qapi/dumpexamples.py | 204 +++++++++++++++++++++++++++++++++++ scripts/qapi/main.py | 5 +- 2 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 scripts/qapi/dumpexamples.py diff --git a/scripts/qapi/dumpexamples.py b/scripts/qapi/dumpexamples.py new file mode 100644 index 0000000000..5a1c275bc8 --- /dev/null +++ b/scripts/qapi/dumpexamples.py @@ -0,0 +1,204 @@ +""" +Dump examples for Developers +""" +# Copyright (c) 2023 Red Hat Inc. +# +# Authors: +# Victor Toso <victortoso@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2. +# See the COPYING file in the top-level directory. + +# Just for type hint on self +from __future__ import annotations + +import os +import json +import random +import string + +from typing import Dict, List, Optional + +from .schema import ( + QAPISchema, + QAPISchemaType, + QAPISchemaVisitor, + QAPISchemaEnumMember, + QAPISchemaFeature, + QAPISchemaIfCond, + QAPISchemaObjectType, + QAPISchemaObjectTypeMember, + QAPISchemaVariants, +) +from .source import QAPISourceInfo + + +def gen_examples(schema: QAPISchema, + output_dir: str, + prefix: str) -> None: + vis = QAPISchemaGenExamplesVisitor(prefix) + schema.visit(vis) + vis.write(output_dir) + + +def get_id(random, size: int) -> str: + letters = string.ascii_lowercase + return ''.join(random.choice(letters) for i in range(size)) + + +def next_object(text, start, end, context) -> (Dict, bool): + # Start of json object + start = text.find("{", start) + end = text.rfind("}", start, end+1) + + # try catch, pretty print issues + try: + ret = json.loads(text[start:end+1]) + except Exception as e: + print("Error: {}\nLocation: {}\nData: {}\n".format( + str(e), context, text[start:end+1])) + return {}, True + else: + return ret, False + + +def parse_text_to_dicts(text: str, context: str) -> (List[Dict], bool): + examples, clients, servers = [], [], [] + failed = False + + count = 1 + c, s = text.find("->"), text.find("<-") + while c != -1 or s != -1: + if c == -1 or (s != -1 and s < c): + start, target = s, servers + else: + start, target = c, clients + + # Find the client and server, if any + if c != -1: + c = text.find("->", start + 1) + if s != -1: + s = text.find("<-", start + 1) + + # Find the limit of current's object. + # We first look for the next message, either client or server. If none + # is avaible, we set the end of the text as limit. + if c == -1 and s != -1: + end = s + elif c != -1 and s == -1: + end = c + elif c != -1 and s != -1: + end = (c < s) and c or s + else: + end = len(text) - 1 + + message, error = next_object(text, start, end, context) + if error: + failed = True + + if len(message) > 0: + message_type = "return" + if "execute" in message: + message_type = "command" + elif "event" in message: + message_type = "event" + + target.append({ + "sequence-order": count, + "message-type": message_type, + "message": message + }) + count += 1 + + examples.append({"client": clients, "server": servers}) + return examples, failed + + +def parse_examples_of(self: QAPISchemaGenExamplesVisitor, + name: str): + + assert(name in self.schema._entity_dict) + obj = self.schema._entity_dict[name] + assert((obj.doc is not None)) + module_name = obj._module.name + + # We initialize random with the name so that we get consistent example + # ids over different generations. The ids of a given example might + # change when adding/removing examples, but that's acceptable as the + # goal is just to grep $id to find what example failed at a given test + # with minimum chorn over regenerating. + random.seed(name, version=2) + + for s in obj.doc.sections: + if s.name != "Example": + continue + + if module_name not in self.target: + self.target[module_name] = [] + + context = f'''{name} at {obj.info.fname}:{obj.info.line}''' + examples, failed = parse_text_to_dicts(s.text, context) + if failed: + # To warn user that docs needs fixing + self.failed = True + + for example in examples: + self.target[module_name].append({ + "id": get_id(random, 10), + "client": example["client"], + "server": example["server"] + }) + + +class QAPISchemaGenExamplesVisitor(QAPISchemaVisitor): + + def __init__(self, prefix: str): + super().__init__() + self.target = {} + self.schema = None + self.failed = False + + def visit_begin(self, schema): + self.schema = schema + + def visit_end(self): + self.schema = None + assert not self.failed, "Should fix the docs" + + def write(self: QAPISchemaGenExamplesVisitor, + output_dir: str) -> None: + for filename, content in self.target.items(): + pathname = os.path.join(output_dir, "examples", filename) + odir = os.path.dirname(pathname) + os.makedirs(odir, exist_ok=True) + result = {"examples": content} + + with open(pathname, "w") as outfile: + outfile.write(json.dumps(result, indent=2, sort_keys=True)) + + def visit_command(self: QAPISchemaGenExamplesVisitor, + name: str, + info: Optional[QAPISourceInfo], + ifcond: QAPISchemaIfCond, + features: List[QAPISchemaFeature], + arg_type: Optional[QAPISchemaObjectType], + ret_type: Optional[QAPISchemaType], + gen: bool, + success_response: bool, + boxed: bool, + allow_oob: bool, + allow_preconfig: bool, + coroutine: bool) -> None: + + if gen: + parse_examples_of(self, name) + + def visit_event(self: QAPISchemaGenExamplesVisitor, + name: str, + info: Optional[QAPISourceInfo], + ifcond: QAPISchemaIfCond, + features: List[QAPISchemaFeature], + arg_type: Optional[QAPISchemaObjectType], + boxed: bool): + + parse_examples_of(self, name) diff --git a/scripts/qapi/main.py b/scripts/qapi/main.py index 7efdcc6b8d..9d71d78b55 100644 --- a/scripts/qapi/main.py +++ b/scripts/qapi/main.py @@ -13,6 +13,7 @@ from .commands import gen_commands from .common import must_match +from .dumpexamples import gen_examples from .error import QAPIError from .events import gen_events from .introspect import gen_introspect @@ -54,7 +55,9 @@ def generate(schema_file: str, gen_commands(schema, output_dir, prefix, gen_tracing) gen_events(schema, output_dir, prefix) gen_introspect(schema, output_dir, prefix, unmask) - + + if not test_schema: + gen_examples(schema, output_dir, prefix) def main() -> int: """ -- 2.41.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-09-11 11:27 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-09-11 11:13 [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators Victor Toso 2023-09-11 11:13 ` [PATCH v2 11/11] qapi: scripts: add a generator for qapi's examples Victor Toso 2023-09-11 11:26 ` [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators Victor Toso -- strict thread matches above, loose matches on Subject: below -- 2023-09-11 10:40 [PATCH v2 00/11] Validate and test qapi examples Victor Toso 2023-09-11 11:27 ` [PATCH v2 10/11] qapi: meson: add test flag to allow skip generators Victor Toso 2023-09-11 11:27 ` [PATCH v2 11/11] qapi: scripts: add a generator for qapi's examples Victor Toso
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).