[{"id":22858,"web_url":"https://patchwork.libcamera.org/comment/22858/","msgid":"<165176015339.1423360.18101672541381501723@Monstersaurus>","date":"2022-05-05T14:15:53","subject":"Re: [libcamera-devel] [PATCH v7 05/13] py: generate control enums\n\tfrom yaml","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Tomi Valkeinen (2022-05-05 11:40:56)\n> Generate enums for controls from control_ids.yaml. The generator script\n> has some heuristics to generate nicer enum names. E.g. instead of having\n> \"LensShadingMapMode.LensShadingMapModeOff\" we get\n> \"LensShadingMapMode.Off\". This heuristics may need to be updated when\n> the yaml file is changed or new controls are added.\n> \n> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n> ---\n>  src/py/libcamera/gen-py-control-enums.py  | 95 +++++++++++++++++++++++\n>  src/py/libcamera/meson.build              |  9 +++\n>  src/py/libcamera/pyenums_generated.cpp.in | 21 +++++\n>  src/py/libcamera/pymain.cpp               |  2 +\n>  4 files changed, 127 insertions(+)\n>  create mode 100755 src/py/libcamera/gen-py-control-enums.py\n>  create mode 100644 src/py/libcamera/pyenums_generated.cpp.in\n> \n> diff --git a/src/py/libcamera/gen-py-control-enums.py b/src/py/libcamera/gen-py-control-enums.py\n> new file mode 100755\n> index 00000000..f1b18389\n> --- /dev/null\n> +++ b/src/py/libcamera/gen-py-control-enums.py\n> @@ -0,0 +1,95 @@\n> +#!/usr/bin/env python3\n> +# SPDX-License-Identifier: GPL-2.0-or-later\n> +#\n> +# Generate Python bindings enums for controls from YAML\n> +\n> +import argparse\n> +import string\n> +import sys\n> +import yaml\n> +\n> +\n> +def find_common_prefix(strings):\n> +    prefix = strings[0]\n> +\n> +    for string in strings[1:]:\n> +        while string[:len(prefix)] != prefix and prefix:\n> +            prefix = prefix[:len(prefix) - 1]\n> +        if not prefix:\n> +            break\n> +\n> +    return prefix\n> +\n> +\n> +def generate_py(controls):\n> +    out = \"\"\n> +\n> +    for ctrl in controls:\n> +        name, ctrl = ctrl.popitem()\n> +\n> +        enum = ctrl.get('enum')\n> +        if not enum:\n> +            continue\n> +\n> +        if ctrl.get('draft'):\n> +            ns = \"libcamera::controls::draft::\"\n> +        else:\n> +            ns = \"libcamera::controls::\"\n> +\n> +        cpp_enum = name + \"Enum\"\n> +\n> +        out += \"\\tpy::enum_<{}{}>(m, \\\"{}\\\")\\n\".format(ns, cpp_enum, name)\n> +\n> +        if name == \"LensShadingMapMode\":\n> +            prefix = \"LensShadingMapMode\"\n\nThis seems a bit arbitrary ...\n\nPerhaps this needs to be in a list. But if there's only one for now - it\ncan be reworked when it comes up I guess?\n\nAnyway, that's what you said in the commit message too, and the rest\nseems ok I think so lets get it tested and in use to find out more ;-)\n\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n\n> +        else:\n> +            prefix = find_common_prefix([e[\"name\"] for e in enum])\n> +\n> +        for entry in enum:\n> +            cpp_enum = entry[\"name\"]\n> +            py_enum = entry[\"name\"][len(prefix):]\n> +\n> +            out += \"\\t\\t.value(\\\"{}\\\", {}{})\\n\".format(py_enum, ns, cpp_enum)\n> +\n> +        out += \"\\t;\\n\"\n> +\n> +    return {\"enums\": out}\n> +\n> +\n> +def fill_template(template, data):\n> +    template = open(template, 'rb').read()\n> +    template = template.decode('utf-8')\n> +    template = string.Template(template)\n> +    return template.substitute(data)\n> +\n> +\n> +def main(argv):\n> +    # Parse command line arguments\n> +    parser = argparse.ArgumentParser()\n> +    parser.add_argument('-o', dest='output', metavar='file', type=str,\n> +                        help='Output file name. Defaults to standard output if not specified.')\n> +    parser.add_argument('input', type=str,\n> +                        help='Input file name.')\n> +    parser.add_argument('template', type=str,\n> +                        help='Template file name.')\n> +    args = parser.parse_args(argv[1:])\n> +\n> +    data = open(args.input, 'rb').read()\n> +    controls = yaml.safe_load(data)['controls']\n> +\n> +    data = generate_py(controls)\n> +\n> +    data = fill_template(args.template, data)\n> +\n> +    if args.output:\n> +        output = open(args.output, 'wb')\n> +        output.write(data.encode('utf-8'))\n> +        output.close()\n> +    else:\n> +        sys.stdout.write(data)\n> +\n> +    return 0\n> +\n> +\n> +if __name__ == '__main__':\n> +    sys.exit(main(sys.argv))\n> diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build\n> index e1f5cf21..42988e55 100644\n> --- a/src/py/libcamera/meson.build\n> +++ b/src/py/libcamera/meson.build\n> @@ -17,6 +17,15 @@ pycamera_sources = files([\n>      'pyenums.cpp',\n>  ])\n>  \n> +gen_input_files = [meson.project_source_root() / 'src/libcamera/control_ids.yaml', 'pyenums_generated.cpp.in']\n> +\n> +generated_sources = custom_target('py_gen_controls',\n> +                                  input : gen_input_files,\n> +                                  output : ['pyenums_generated.cpp'],\n> +                                  command : ['gen-py-control-enums.py', '-o', '@OUTPUT@', '@INPUT@'])\n> +\n> +pycamera_sources += generated_sources\n> +\n>  pycamera_deps = [\n>      libcamera_public,\n>      py3_dep,\n> diff --git a/src/py/libcamera/pyenums_generated.cpp.in b/src/py/libcamera/pyenums_generated.cpp.in\n> new file mode 100644\n> index 00000000..96daf257\n> --- /dev/null\n> +++ b/src/py/libcamera/pyenums_generated.cpp.in\n> @@ -0,0 +1,21 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2021, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n> + *\n> + * Python bindings\n> + *\n> + * This file is auto-generated. Do not edit.\n> + */\n> +\n> +#include <libcamera/libcamera.h>\n> +\n> +#include <pybind11/smart_holder.h>\n> +\n> +namespace py = pybind11;\n> +\n> +using namespace libcamera;\n> +\n> +void init_pyenums_generated(py::module& m)\n> +{\n> +${enums}\n> +}\n> diff --git a/src/py/libcamera/pymain.cpp b/src/py/libcamera/pymain.cpp\n> index 54674caf..81d48a20 100644\n> --- a/src/py/libcamera/pymain.cpp\n> +++ b/src/py/libcamera/pymain.cpp\n> @@ -115,10 +115,12 @@ static void handleRequestCompleted(Request *req)\n>  }\n>  \n>  void init_pyenums(py::module &m);\n> +void init_pyenums_generated(py::module &m);\n>  \n>  PYBIND11_MODULE(_libcamera, m)\n>  {\n>         init_pyenums(m);\n> +       init_pyenums_generated(m);\n>  \n>         /* Forward declarations */\n>  \n> -- \n> 2.34.1\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 7119FC3256\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  5 May 2022 14:15:58 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 74D7765646;\n\tThu,  5 May 2022 16:15:57 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 867ED603AB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 May 2022 16:15:56 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 05FC9492;\n\tThu,  5 May 2022 16:15:55 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1651760157;\n\tbh=DOqEvDihRKq63kMcz3FuJrPxyEROiNDRdGx09mFaBvk=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=eGV2ZG0YZtQTO6uep7SuhzHnqFxrCBSE3MwmEDbEP0MdV+z6TrVur222R5Rz8eBI7\n\tcJzmE8ZSNSRc9SomQtsTApkqjGtU/Sytu2FIh1VsC0Dm01F47eN3YPJxz+E1/aeQqT\n\tqSyn6GWojgqBb9yzsanx3j/OgVJMjRs7ZafrviU1/KLk7LifFNbu1LtrYULoZDaqcg\n\t0pG7+TLmGb8fp12e8i0rEbJIGhTgzvMthJKNojNULP0PzqPauD9DUov6jyxkfYmeDn\n\tBMNIdKIxVnOjkiIAjxmPxj0W7eTbreqRcSlzfHbT8qirSCAwSRJL2/ioO8/TsdDQUw\n\tHN/ypSd3rBQoQ==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1651760156;\n\tbh=DOqEvDihRKq63kMcz3FuJrPxyEROiNDRdGx09mFaBvk=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=Rq2G9nAznCEXo6mTAUTBYsDYWKRQs7C3D5s/EHpN/nPnbf9STrbFuTOzPYWTAZMsz\n\tO7hSWgrh6zYNrIc1PEg1Oj426wbFnKUeDnx4cUM9x05zPILZzUw8z1fmhmAPG7x7VP\n\tGOIqHJTAlOE71y0YqmJFTJgnqxJKD6y84y5rAj3U="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"Rq2G9nAz\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20220505104104.70841-6-tomi.valkeinen@ideasonboard.com>","References":"<20220505104104.70841-1-tomi.valkeinen@ideasonboard.com>\n\t<20220505104104.70841-6-tomi.valkeinen@ideasonboard.com>","To":"David Plowman <david.plowman@raspberrypi.com>,\n\tJacopo Mondi <jacopo@jmondi.org>,\n\tLaurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tTomi Valkeinen <tomi.valkeinen@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Thu, 05 May 2022 15:15:53 +0100","Message-ID":"<165176015339.1423360.18101672541381501723@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH v7 05/13] py: generate control enums\n\tfrom yaml","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":22864,"web_url":"https://patchwork.libcamera.org/comment/22864/","msgid":"<YnQLxAmFJ8kPcpSW@pendragon.ideasonboard.com>","date":"2022-05-05T17:39:16","subject":"Re: [libcamera-devel] [PATCH v7 05/13] py: generate control enums\n\tfrom yaml","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Thu, May 05, 2022 at 03:15:53PM +0100, Kieran Bingham wrote:\n> Quoting Tomi Valkeinen (2022-05-05 11:40:56)\n> > Generate enums for controls from control_ids.yaml. The generator script\n> > has some heuristics to generate nicer enum names. E.g. instead of having\n> > \"LensShadingMapMode.LensShadingMapModeOff\" we get\n> > \"LensShadingMapMode.Off\". This heuristics may need to be updated when\n> > the yaml file is changed or new controls are added.\n\nMaybe we should do the same in C++, with enum class ?\n\n> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n> > ---\n> >  src/py/libcamera/gen-py-control-enums.py  | 95 +++++++++++++++++++++++\n> >  src/py/libcamera/meson.build              |  9 +++\n> >  src/py/libcamera/pyenums_generated.cpp.in | 21 +++++\n> >  src/py/libcamera/pymain.cpp               |  2 +\n> >  4 files changed, 127 insertions(+)\n> >  create mode 100755 src/py/libcamera/gen-py-control-enums.py\n> >  create mode 100644 src/py/libcamera/pyenums_generated.cpp.in\n> > \n> > diff --git a/src/py/libcamera/gen-py-control-enums.py b/src/py/libcamera/gen-py-control-enums.py\n> > new file mode 100755\n> > index 00000000..f1b18389\n> > --- /dev/null\n> > +++ b/src/py/libcamera/gen-py-control-enums.py\n> > @@ -0,0 +1,95 @@\n> > +#!/usr/bin/env python3\n> > +# SPDX-License-Identifier: GPL-2.0-or-later\n> > +#\n> > +# Generate Python bindings enums for controls from YAML\n> > +\n> > +import argparse\n> > +import string\n> > +import sys\n> > +import yaml\n> > +\n> > +\n> > +def find_common_prefix(strings):\n> > +    prefix = strings[0]\n> > +\n> > +    for string in strings[1:]:\n> > +        while string[:len(prefix)] != prefix and prefix:\n> > +            prefix = prefix[:len(prefix) - 1]\n> > +        if not prefix:\n> > +            break\n> > +\n> > +    return prefix\n> > +\n> > +\n> > +def generate_py(controls):\n> > +    out = \"\"\n\nThe other python scripts use single quotes for strings, could you\nstandardize on that ? You already use single quotes in several locations\nin this script actually.\n\n> > +\n> > +    for ctrl in controls:\n> > +        name, ctrl = ctrl.popitem()\n> > +\n> > +        enum = ctrl.get('enum')\n> > +        if not enum:\n> > +            continue\n> > +\n> > +        if ctrl.get('draft'):\n> > +            ns = \"libcamera::controls::draft::\"\n> > +        else:\n> > +            ns = \"libcamera::controls::\"\n> > +\n> > +        cpp_enum = name + \"Enum\"\n> > +\n> > +        out += \"\\tpy::enum_<{}{}>(m, \\\"{}\\\")\\n\".format(ns, cpp_enum, name)\n> > +\n> > +        if name == \"LensShadingMapMode\":\n> > +            prefix = \"LensShadingMapMode\"\n> \n> This seems a bit arbitrary ...\n> \n> Perhaps this needs to be in a list. But if there's only one for now - it\n> can be reworked when it comes up I guess?\n> \n> Anyway, that's what you said in the commit message too, and the rest\n> seems ok I think so lets get it tested and in use to find out more ;-)\n> \n> \n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> \n> \n> > +        else:\n> > +            prefix = find_common_prefix([e[\"name\"] for e in enum])\n> > +\n> > +        for entry in enum:\n> > +            cpp_enum = entry[\"name\"]\n> > +            py_enum = entry[\"name\"][len(prefix):]\n> > +\n> > +            out += \"\\t\\t.value(\\\"{}\\\", {}{})\\n\".format(py_enum, ns, cpp_enum)\n> > +\n> > +        out += \"\\t;\\n\"\n> > +\n> > +    return {\"enums\": out}\n> > +\n> > +\n> > +def fill_template(template, data):\n> > +    template = open(template, 'rb').read()\n> > +    template = template.decode('utf-8')\n> > +    template = string.Template(template)\n> > +    return template.substitute(data)\n> > +\n> > +\n> > +def main(argv):\n> > +    # Parse command line arguments\n> > +    parser = argparse.ArgumentParser()\n> > +    parser.add_argument('-o', dest='output', metavar='file', type=str,\n> > +                        help='Output file name. Defaults to standard output if not specified.')\n> > +    parser.add_argument('input', type=str,\n> > +                        help='Input file name.')\n> > +    parser.add_argument('template', type=str,\n> > +                        help='Template file name.')\n> > +    args = parser.parse_args(argv[1:])\n> > +\n> > +    data = open(args.input, 'rb').read()\n> > +    controls = yaml.safe_load(data)['controls']\n> > +\n> > +    data = generate_py(controls)\n> > +\n> > +    data = fill_template(args.template, data)\n> > +\n> > +    if args.output:\n> > +        output = open(args.output, 'wb')\n> > +        output.write(data.encode('utf-8'))\n> > +        output.close()\n> > +    else:\n> > +        sys.stdout.write(data)\n> > +\n> > +    return 0\n> > +\n> > +\n> > +if __name__ == '__main__':\n> > +    sys.exit(main(sys.argv))\n> > diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build\n> > index e1f5cf21..42988e55 100644\n> > --- a/src/py/libcamera/meson.build\n> > +++ b/src/py/libcamera/meson.build\n> > @@ -17,6 +17,15 @@ pycamera_sources = files([\n> >      'pyenums.cpp',\n> >  ])\n> >  \n> > +gen_input_files = [meson.project_source_root() / 'src/libcamera/control_ids.yaml', 'pyenums_generated.cpp.in']\n\ngen_input_files = [\n    meson.project_source_root() / 'src/libcamera/control_ids.yaml',\n    'pyenums_generated.cpp.in',\n]\n\nPossibly with\n\n    meson.project_source_root() / 'src' / 'libcamera' / 'control_ids.yaml',\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> > +\n> > +generated_sources = custom_target('py_gen_controls',\n> > +                                  input : gen_input_files,\n> > +                                  output : ['pyenums_generated.cpp'],\n> > +                                  command : ['gen-py-control-enums.py', '-o', '@OUTPUT@', '@INPUT@'])\n> > +\n> > +pycamera_sources += generated_sources\n> > +\n> >  pycamera_deps = [\n> >      libcamera_public,\n> >      py3_dep,\n> > diff --git a/src/py/libcamera/pyenums_generated.cpp.in b/src/py/libcamera/pyenums_generated.cpp.in\n> > new file mode 100644\n> > index 00000000..96daf257\n> > --- /dev/null\n> > +++ b/src/py/libcamera/pyenums_generated.cpp.in\n> > @@ -0,0 +1,21 @@\n> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> > +/*\n> > + * Copyright (C) 2021, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n> > + *\n> > + * Python bindings\n> > + *\n> > + * This file is auto-generated. Do not edit.\n> > + */\n> > +\n> > +#include <libcamera/libcamera.h>\n> > +\n> > +#include <pybind11/smart_holder.h>\n> > +\n> > +namespace py = pybind11;\n> > +\n> > +using namespace libcamera;\n> > +\n> > +void init_pyenums_generated(py::module& m)\n> > +{\n> > +${enums}\n> > +}\n> > diff --git a/src/py/libcamera/pymain.cpp b/src/py/libcamera/pymain.cpp\n> > index 54674caf..81d48a20 100644\n> > --- a/src/py/libcamera/pymain.cpp\n> > +++ b/src/py/libcamera/pymain.cpp\n> > @@ -115,10 +115,12 @@ static void handleRequestCompleted(Request *req)\n> >  }\n> >  \n> >  void init_pyenums(py::module &m);\n> > +void init_pyenums_generated(py::module &m);\n> >  \n> >  PYBIND11_MODULE(_libcamera, m)\n> >  {\n> >         init_pyenums(m);\n> > +       init_pyenums_generated(m);\n> >  \n> >         /* Forward declarations */\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 982FEC0F2A\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  5 May 2022 17:39:21 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E09D265643;\n\tThu,  5 May 2022 19:39:20 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6856D603AB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 May 2022 19:39:20 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id A354F492;\n\tThu,  5 May 2022 19:39:19 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1651772360;\n\tbh=enMDaYQnto8QKlNqYmCNcCpmgLjVFTemc6yq2rNwUPs=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=QQQPxmbcwBYLWSCzht9rFUevfpxbryNtpvf73Tcvf3tKrFjEW+iCeenLBG1wvlH8N\n\t73hibVzZKFGlC+YAexcaow2mTz2lg7utybD4mqk+L4+Wy7RM+O/fD1qEOjLartoUFo\n\tDn11/Y0guu8B5WG/ZXZCznvPOQBDMTowarS6CmeRfVHxAhutlDSuYpEzOxlZ3Y2cRg\n\tpVS5JNdUirDX/cGUQXDpzWOGHZXSFK1/l1Re/M3O44bw35e73ZjglVy7I5aS+DUuNY\n\tc+2QUV2Jzt+ZCv367jlTSKXWa5hj5z2zaIDFPMtXsgsxarS9EL1kR3M78ahrLm4jLs\n\t/MvCWvutnJkNg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1651772359;\n\tbh=enMDaYQnto8QKlNqYmCNcCpmgLjVFTemc6yq2rNwUPs=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=GPbbFedfQ5UM+y+CQxB3QwUgy+eNbxmy37dMEjrNJMBdaBQ6lLvu3E2ONvaLBLiOz\n\tCXjwGklt9MQYfrxvNGm3yBY+WzJ6SShceJNTDT/XrAX2L32IQdx2Mt0GQlmAndBgF7\n\tE6fbPilJgQJ5PDSI60bI5MktVPetLah75GMgF1YE="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"GPbbFedf\"; dkim-atps=neutral","Date":"Thu, 5 May 2022 20:39:16 +0300","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Message-ID":"<YnQLxAmFJ8kPcpSW@pendragon.ideasonboard.com>","References":"<20220505104104.70841-1-tomi.valkeinen@ideasonboard.com>\n\t<20220505104104.70841-6-tomi.valkeinen@ideasonboard.com>\n\t<165176015339.1423360.18101672541381501723@Monstersaurus>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<165176015339.1423360.18101672541381501723@Monstersaurus>","Subject":"Re: [libcamera-devel] [PATCH v7 05/13] py: generate control enums\n\tfrom yaml","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]