[{"id":30752,"web_url":"https://patchwork.libcamera.org/comment/30752/","msgid":"<a63a4dce-9ca6-4a5e-8bd1-0e0b63c84799@ideasonboard.com>","date":"2024-08-12T14:33:57","subject":"Re: [PATCH 09/10] py: gen-py-controls: Use Control class","submitter":{"id":109,"url":"https://patchwork.libcamera.org/api/people/109/","name":"Tomi Valkeinen","email":"tomi.valkeinen@ideasonboard.com"},"content":"On 09/08/2024 03:59, Laurent Pinchart wrote:\n> Replace manual extraction of data from YAML with the Control helper\n> class. This centralizes YAML parsing and avoids manual mistakes.\n> \n> In order to import the controls module, add the utils/codegen/ directory\n> to the PYTHONPATH through the Python build environment.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>   src/py/libcamera/gen-py-controls.py | 32 ++++++++++++++---------------\n>   src/py/libcamera/meson.build        |  6 ++++--\n>   utils/codegen/meson.build           |  1 +\n>   3 files changed, 21 insertions(+), 18 deletions(-)\n> \n> diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py\n> index 8efbf95b9433..a18dc5337090 100755\n> --- a/src/py/libcamera/gen-py-controls.py\n> +++ b/src/py/libcamera/gen-py-controls.py\n> @@ -8,6 +8,8 @@ import string\n>   import sys\n>   import yaml\n>   \n> +from controls import Control\n> +\n>   \n>   def find_common_prefix(strings):\n>       prefix = strings[0]\n> @@ -28,9 +30,7 @@ def generate_py(controls, mode):\n>       vendor_defs = []\n>       vendors = []\n>       for vendor, ctrl_list in controls.items():\n> -        for ctrls in ctrl_list:\n> -            name, ctrl = ctrls.popitem()\n> -\n> +        for ctrl in ctrl_list:\n>               if vendor not in vendors and vendor != 'libcamera':\n>                   vendor_mode_str = f'{vendor.capitalize()}{mode.capitalize()}'\n>                   vendors_class_def.append('class Py{}\\n{{\\n}};\\n'.format(vendor_mode_str))\n> @@ -44,29 +44,28 @@ def generate_py(controls, mode):\n>                   ns = 'libcamera::{}::'.format(mode)\n>                   container = 'controls'\n>   \n> -            out += f'\\t{container}.def_readonly_static(\"{name}\", static_cast<const libcamera::ControlId *>(&{ns}{name}));\\n\\n'\n> +            out += f'\\t{container}.def_readonly_static(\"{ctrl.name}\", static_cast<const libcamera::ControlId *>(&{ns}{ctrl.name}));\\n\\n'\n>   \n> -            enum = ctrl.get('enum')\n> -            if not enum:\n> +            if not ctrl.is_enum:\n>                   continue\n>   \n> -            cpp_enum = name + 'Enum'\n> +            cpp_enum = ctrl.name + 'Enum'\n>   \n>               out += '\\tpy::enum_<{}{}>({}, \\\"{}\\\")\\n'.format(ns, cpp_enum, container, cpp_enum)\n>   \n>               if mode == 'controls':\n>                   # Adjustments for controls\n> -                if name == 'LensShadingMapMode':\n> +                if ctrl.name == 'LensShadingMapMode':\n>                       prefix = 'LensShadingMapMode'\n>                   else:\n> -                    prefix = find_common_prefix([e['name'] for e in enum])\n> +                    prefix = find_common_prefix([e.name for e in ctrl.enum_values])\n>               else:\n>                   # Adjustments for properties\n> -                prefix = find_common_prefix([e['name'] for e in enum])\n> +                prefix = find_common_prefix([e.name for e in ctrl.enum_values])\n>   \n> -            for entry in enum:\n> -                cpp_enum = entry['name']\n> -                py_enum = entry['name'][len(prefix):]\n> +            for entry in ctrl.enum_values:\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> @@ -103,9 +102,10 @@ def main(argv):\n>   \n>       controls = {}\n>       for input in args.input:\n> -        data = open(input, 'rb').read()\n> -        vendor = yaml.safe_load(data)['vendor']\n> -        controls[vendor] = yaml.safe_load(data)['controls']\n> +        data = yaml.safe_load(open(input, 'rb').read())\n> +        vendor = data['vendor']\n> +        ctrls = data['controls']\n> +        controls[vendor] = [Control(*ctrl.popitem(), vendor) for ctrl in ctrls]\n>   \n>       data = generate_py(controls, args.mode)\n>   \n> diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build\n> index 2e67407598db..6ad2d7713e4d 100644\n> --- a/src/py/libcamera/meson.build\n> +++ b/src/py/libcamera/meson.build\n> @@ -35,7 +35,8 @@ pycamera_sources += custom_target('py_gen_controls',\n>                                     input : controls_files,\n>                                     output : ['py_controls_generated.cpp'],\n>                                     command : [gen_py_controls, '--mode', 'controls', '-o', '@OUTPUT@',\n> -                                             '-t', gen_py_controls_template, '@INPUT@'])\n> +                                             '-t', gen_py_controls_template, '@INPUT@'],\n> +                                  env : py_build_env)\n>   \n>   # Generate properties\n>   \n> @@ -45,7 +46,8 @@ pycamera_sources += custom_target('py_gen_properties',\n>                                     input : properties_files,\n>                                     output : ['py_properties_generated.cpp'],\n>                                     command : [gen_py_controls, '--mode', 'properties', '-o', '@OUTPUT@',\n> -                                             '-t', gen_py_properties_template, '@INPUT@'])\n> +                                             '-t', gen_py_properties_template, '@INPUT@'],\n> +                                  env : py_build_env)\n>   \n>   # Generate formats\n>   \n> diff --git a/utils/codegen/meson.build b/utils/codegen/meson.build\n> index fb2196ee0d20..adf33bbab9e1 100644\n> --- a/utils/codegen/meson.build\n> +++ b/utils/codegen/meson.build\n> @@ -5,6 +5,7 @@\n>   py_build_env = environment()\n>   # \\todo Investigate usage of PYTHONPYCACHEPREFIX for Python >= 3.8\n>   py_build_env.set('PYTHONDONTWRITEBYTECODE', '1')\n> +py_build_env.prepend('PYTHONPATH', meson.current_source_dir())\n>   \n>   py_modules += ['jinja2', 'yaml']\n>   \n\nReviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n\n  Tomi","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 6FC67C323E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 12 Aug 2024 14:34:02 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 29EA9633BA;\n\tMon, 12 Aug 2024 16:34:02 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 1970F63369\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 12 Aug 2024 16:34:00 +0200 (CEST)","from [192.168.88.20] (91-156-87-48.elisa-laajakaista.fi\n\t[91.156.87.48])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id AF110836;\n\tMon, 12 Aug 2024 16:33:03 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"NDwk3705\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1723473183;\n\tbh=TZ3ms+K5BaiusuFJrf6lzSyzwMWfge9KXsCZ+3z69e4=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=NDwk37055BbhE52Em+HdNDnei7DNqZj/L3DcetBf5PwHfbMlcICjE7G9C6ZgkJup2\n\tNCJ0hSS3cbd6Yzzzl+UJ9kozRxi7cH/MpacHIAoWtWSqyzlED+3DmiOSJc9YVA84e4\n\t2GURBp1Wa8Ok3MOfeCCMryF83qbN7VSy4Da+jFfE=","Message-ID":"<a63a4dce-9ca6-4a5e-8bd1-0e0b63c84799@ideasonboard.com>","Date":"Mon, 12 Aug 2024 17:33:57 +0300","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH 09/10] py: gen-py-controls: Use Control class","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20240809005914.20662-1-laurent.pinchart@ideasonboard.com>\n\t<20240809005914.20662-10-laurent.pinchart@ideasonboard.com>","Content-Language":"en-US","From":"Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>","Autocrypt":"addr=tomi.valkeinen@ideasonboard.com; keydata=\n\t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","In-Reply-To":"<20240809005914.20662-10-laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":30834,"web_url":"https://patchwork.libcamera.org/comment/30834/","msgid":"<Zr2LMMRHU75EKRvE@pyrite.rasen.tech>","date":"2024-08-15T04:59:28","subject":"Re: [PATCH 09/10] py: gen-py-controls: Use Control class","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"On Fri, Aug 09, 2024 at 03:59:13AM +0300, Laurent Pinchart wrote:\n> Replace manual extraction of data from YAML with the Control helper\n> class. This centralizes YAML parsing and avoids manual mistakes.\n> \n> In order to import the controls module, add the utils/codegen/ directory\n> to the PYTHONPATH through the Python build environment.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nReviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n\n> ---\n>  src/py/libcamera/gen-py-controls.py | 32 ++++++++++++++---------------\n>  src/py/libcamera/meson.build        |  6 ++++--\n>  utils/codegen/meson.build           |  1 +\n>  3 files changed, 21 insertions(+), 18 deletions(-)\n> \n> diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py\n> index 8efbf95b9433..a18dc5337090 100755\n> --- a/src/py/libcamera/gen-py-controls.py\n> +++ b/src/py/libcamera/gen-py-controls.py\n> @@ -8,6 +8,8 @@ import string\n>  import sys\n>  import yaml\n>  \n> +from controls import Control\n> +\n>  \n>  def find_common_prefix(strings):\n>      prefix = strings[0]\n> @@ -28,9 +30,7 @@ def generate_py(controls, mode):\n>      vendor_defs = []\n>      vendors = []\n>      for vendor, ctrl_list in controls.items():\n> -        for ctrls in ctrl_list:\n> -            name, ctrl = ctrls.popitem()\n> -\n> +        for ctrl in ctrl_list:\n>              if vendor not in vendors and vendor != 'libcamera':\n>                  vendor_mode_str = f'{vendor.capitalize()}{mode.capitalize()}'\n>                  vendors_class_def.append('class Py{}\\n{{\\n}};\\n'.format(vendor_mode_str))\n> @@ -44,29 +44,28 @@ def generate_py(controls, mode):\n>                  ns = 'libcamera::{}::'.format(mode)\n>                  container = 'controls'\n>  \n> -            out += f'\\t{container}.def_readonly_static(\"{name}\", static_cast<const libcamera::ControlId *>(&{ns}{name}));\\n\\n'\n> +            out += f'\\t{container}.def_readonly_static(\"{ctrl.name}\", static_cast<const libcamera::ControlId *>(&{ns}{ctrl.name}));\\n\\n'\n>  \n> -            enum = ctrl.get('enum')\n> -            if not enum:\n> +            if not ctrl.is_enum:\n>                  continue\n>  \n> -            cpp_enum = name + 'Enum'\n> +            cpp_enum = ctrl.name + 'Enum'\n>  \n>              out += '\\tpy::enum_<{}{}>({}, \\\"{}\\\")\\n'.format(ns, cpp_enum, container, cpp_enum)\n>  \n>              if mode == 'controls':\n>                  # Adjustments for controls\n> -                if name == 'LensShadingMapMode':\n> +                if ctrl.name == 'LensShadingMapMode':\n>                      prefix = 'LensShadingMapMode'\n>                  else:\n> -                    prefix = find_common_prefix([e['name'] for e in enum])\n> +                    prefix = find_common_prefix([e.name for e in ctrl.enum_values])\n>              else:\n>                  # Adjustments for properties\n> -                prefix = find_common_prefix([e['name'] for e in enum])\n> +                prefix = find_common_prefix([e.name for e in ctrl.enum_values])\n>  \n> -            for entry in enum:\n> -                cpp_enum = entry['name']\n> -                py_enum = entry['name'][len(prefix):]\n> +            for entry in ctrl.enum_values:\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> @@ -103,9 +102,10 @@ def main(argv):\n>  \n>      controls = {}\n>      for input in args.input:\n> -        data = open(input, 'rb').read()\n> -        vendor = yaml.safe_load(data)['vendor']\n> -        controls[vendor] = yaml.safe_load(data)['controls']\n> +        data = yaml.safe_load(open(input, 'rb').read())\n> +        vendor = data['vendor']\n> +        ctrls = data['controls']\n> +        controls[vendor] = [Control(*ctrl.popitem(), vendor) for ctrl in ctrls]\n>  \n>      data = generate_py(controls, args.mode)\n>  \n> diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build\n> index 2e67407598db..6ad2d7713e4d 100644\n> --- a/src/py/libcamera/meson.build\n> +++ b/src/py/libcamera/meson.build\n> @@ -35,7 +35,8 @@ pycamera_sources += custom_target('py_gen_controls',\n>                                    input : controls_files,\n>                                    output : ['py_controls_generated.cpp'],\n>                                    command : [gen_py_controls, '--mode', 'controls', '-o', '@OUTPUT@',\n> -                                             '-t', gen_py_controls_template, '@INPUT@'])\n> +                                             '-t', gen_py_controls_template, '@INPUT@'],\n> +                                  env : py_build_env)\n>  \n>  # Generate properties\n>  \n> @@ -45,7 +46,8 @@ pycamera_sources += custom_target('py_gen_properties',\n>                                    input : properties_files,\n>                                    output : ['py_properties_generated.cpp'],\n>                                    command : [gen_py_controls, '--mode', 'properties', '-o', '@OUTPUT@',\n> -                                             '-t', gen_py_properties_template, '@INPUT@'])\n> +                                             '-t', gen_py_properties_template, '@INPUT@'],\n> +                                  env : py_build_env)\n>  \n>  # Generate formats\n>  \n> diff --git a/utils/codegen/meson.build b/utils/codegen/meson.build\n> index fb2196ee0d20..adf33bbab9e1 100644\n> --- a/utils/codegen/meson.build\n> +++ b/utils/codegen/meson.build\n> @@ -5,6 +5,7 @@\n>  py_build_env = environment()\n>  # \\todo Investigate usage of PYTHONPYCACHEPREFIX for Python >= 3.8\n>  py_build_env.set('PYTHONDONTWRITEBYTECODE', '1')\n> +py_build_env.prepend('PYTHONPATH', meson.current_source_dir())\n>  \n>  py_modules += ['jinja2', 'yaml']\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 76EECBDB13\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 15 Aug 2024 04:59:38 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 9775363382;\n\tThu, 15 Aug 2024 06:59:37 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C625C63382\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 15 Aug 2024 06:59:35 +0200 (CEST)","from pyrite.rasen.tech (h175-177-049-024.catv02.itscom.jp\n\t[175.177.49.24])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 95B446CA;\n\tThu, 15 Aug 2024 06:58:36 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"vuWS2dt8\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1723697917;\n\tbh=nLxxJGCoi4kesOjv8llFctsTBB72LI7KqAwa+4sfycQ=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=vuWS2dt8W6GaiKsZbyCgS8/a2Qqz7+PkaSTZDNjs4eAh4oOZpLnynO58sqfBiJ9yJ\n\tnsPkwPJbyIUxqw7e3i8vjX8rNf1lHcfTzY58+CQ7el3ZD6+h32DNHLFC6p3Zzzc3kK\n\tPQkuV1TvHFXLF+M7Jkls/SeatYopGP1W9ns5xUsQ=","Date":"Thu, 15 Aug 2024 13:59:28 +0900","From":"Paul Elder <paul.elder@ideasonboard.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 09/10] py: gen-py-controls: Use Control class","Message-ID":"<Zr2LMMRHU75EKRvE@pyrite.rasen.tech>","References":"<20240809005914.20662-1-laurent.pinchart@ideasonboard.com>\n\t<20240809005914.20662-10-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20240809005914.20662-10-laurent.pinchart@ideasonboard.com>","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]