[v1,1/2] utils: codegen: gen-formats.py: Use jinja
diff mbox series

Message ID 20250901092320.44615-1-barnabas.pocze@ideasonboard.com
State New
Headers show
Series
  • [v1,1/2] utils: codegen: gen-formats.py: Use jinja
Related show

Commit Message

Barnabás Pőcze Sept. 1, 2025, 9:23 a.m. UTC
Currently the gen-formats.py script can only be used to generate C++
code because it hard-codes part of the template. Use jinja to fully
remove any such dependency.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
---
 include/libcamera/formats.h.in |  4 +++-
 utils/codegen/gen-formats.py   | 34 ++++++++++++----------------------
 2 files changed, 15 insertions(+), 23 deletions(-)

Comments

Kieran Bingham Sept. 1, 2025, 1:25 p.m. UTC | #1
Quoting Barnabás Pőcze (2025-09-01 10:23:19)
> Currently the gen-formats.py script can only be used to generate C++
> code because it hard-codes part of the template. Use jinja to fully
> remove any such dependency.
> 


Is there a plan to generate format information elsewhere than the C++
header after this ?



> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> ---
>  include/libcamera/formats.h.in |  4 +++-
>  utils/codegen/gen-formats.py   | 34 ++++++++++++----------------------
>  2 files changed, 15 insertions(+), 23 deletions(-)
> 
> diff --git a/include/libcamera/formats.h.in b/include/libcamera/formats.h.in
> index 6ae7634fe..5ff9c3bf4 100644
> --- a/include/libcamera/formats.h.in
> +++ b/include/libcamera/formats.h.in
> @@ -35,7 +35,9 @@ constexpr uint64_t __mod(unsigned int vendor, unsigned int mod)
>  
>  } /* namespace */
>  
> -${formats}
> +{% for f in formats %}
> +constexpr PixelFormat {{f.name}}(__fourcc({{f.fourcc}}), __mod({{f.mod}}));
> +{%- endfor %}
>  
>  } /* namespace formats */
>  
> diff --git a/utils/codegen/gen-formats.py b/utils/codegen/gen-formats.py
> index 0c0932a5b..872f3fe34 100755
> --- a/utils/codegen/gen-formats.py
> +++ b/utils/codegen/gen-formats.py
> @@ -7,6 +7,7 @@
>  # Generate formats definitions from YAML
>  
>  import argparse
> +import jinja2
>  import re
>  import string
>  import sys
> @@ -52,9 +53,7 @@ class DRMFourCC(object):
>          return self.vendors[vendor], value
>  
>  
> -def generate_h(formats, drm_fourcc):
> -    template = string.Template('constexpr PixelFormat ${name}{ __fourcc(${fourcc}), __mod(${mod}) };')
> -
> +def generate_formats(formats, drm_fourcc):
>      fmts = []
>  
>      for format in formats:
> @@ -73,24 +72,17 @@ def generate_h(formats, drm_fourcc):
>          if mod:
>              data['mod'] = '%u, %u' % drm_fourcc.mod(mod)
>  
> -        fmts.append(template.substitute(data))
> -
> -    return {'formats': '\n'.join(fmts)}
> -
> -
> -def fill_template(template, data):
> +        fmts.append(data)
>  
> -    template = open(template, 'rb').read()
> -    template = template.decode('utf-8')
> -    template = string.Template(template)
> -    return template.substitute(data)
> +    return fmts
>  
>  
>  def main(argv):
>  
>      # Parse command line arguments
>      parser = argparse.ArgumentParser()
> -    parser.add_argument('-o', dest='output', metavar='file', type=str,
> +    parser.add_argument('-o', dest='output', metavar='file',
> +                        type=argparse.FileType('w', encoding='utf-8'), default=sys.stdout,
>                          help='Output file name. Defaults to standard output if not specified.')
>      parser.add_argument('input', type=str,
>                          help='Input file name.')
> @@ -104,15 +96,13 @@ def main(argv):
>      formats = yaml.safe_load(data)['formats']
>      drm_fourcc = DRMFourCC(args.drm_fourcc)
>  
> -    data = generate_h(formats, drm_fourcc)
> -    data = fill_template(args.template, data)
> +    env = jinja2.Environment()
> +    template = env.from_string(open(args.template, 'r', encoding='utf-8').read())
> +    string = template.render({
> +        'formats': generate_formats(formats, drm_fourcc),
> +    })
>  
> -    if args.output:
> -        output = open(args.output, 'wb')
> -        output.write(data.encode('utf-8'))
> -        output.close()
> -    else:
> -        sys.stdout.write(data)
> +    args.output.write(string)

This looks reasonable to me.

All looks ok to me and we already use jinja so :

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

>  
>      return 0
>  
> -- 
> 2.51.0
>
Barnabás Pőcze Sept. 1, 2025, 1:34 p.m. UTC | #2
Hi

2025. 09. 01. 15:25 keltezéssel, Kieran Bingham írta:
> Quoting Barnabás Pőcze (2025-09-01 10:23:19)
>> Currently the gen-formats.py script can only be used to generate C++
>> code because it hard-codes part of the template. Use jinja to fully
>> remove any such dependency.
>>
> 
> 
> Is there a plan to generate format information elsewhere than the C++
> header after this ?

Possibly, I'm not entirely sure yet. I needed it for some experiments.
And the next change also depends on it. And many things already use jinja.


Regards,
Barnabás Pőcze


> 
> 
> 
>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
>> ---
>>   include/libcamera/formats.h.in |  4 +++-
>>   utils/codegen/gen-formats.py   | 34 ++++++++++++----------------------
>>   2 files changed, 15 insertions(+), 23 deletions(-)
>>
>> diff --git a/include/libcamera/formats.h.in b/include/libcamera/formats.h.in
>> index 6ae7634fe..5ff9c3bf4 100644
>> --- a/include/libcamera/formats.h.in
>> +++ b/include/libcamera/formats.h.in
>> @@ -35,7 +35,9 @@ constexpr uint64_t __mod(unsigned int vendor, unsigned int mod)
>>   
>>   } /* namespace */
>>   
>> -${formats}
>> +{% for f in formats %}
>> +constexpr PixelFormat {{f.name}}(__fourcc({{f.fourcc}}), __mod({{f.mod}}));
>> +{%- endfor %}
>>   
>>   } /* namespace formats */
>>   
>> diff --git a/utils/codegen/gen-formats.py b/utils/codegen/gen-formats.py
>> index 0c0932a5b..872f3fe34 100755
>> --- a/utils/codegen/gen-formats.py
>> +++ b/utils/codegen/gen-formats.py
>> @@ -7,6 +7,7 @@
>>   # Generate formats definitions from YAML
>>   
>>   import argparse
>> +import jinja2
>>   import re
>>   import string
>>   import sys
>> @@ -52,9 +53,7 @@ class DRMFourCC(object):
>>           return self.vendors[vendor], value
>>   
>>   
>> -def generate_h(formats, drm_fourcc):
>> -    template = string.Template('constexpr PixelFormat ${name}{ __fourcc(${fourcc}), __mod(${mod}) };')
>> -
>> +def generate_formats(formats, drm_fourcc):
>>       fmts = []
>>   
>>       for format in formats:
>> @@ -73,24 +72,17 @@ def generate_h(formats, drm_fourcc):
>>           if mod:
>>               data['mod'] = '%u, %u' % drm_fourcc.mod(mod)
>>   
>> -        fmts.append(template.substitute(data))
>> -
>> -    return {'formats': '\n'.join(fmts)}
>> -
>> -
>> -def fill_template(template, data):
>> +        fmts.append(data)
>>   
>> -    template = open(template, 'rb').read()
>> -    template = template.decode('utf-8')
>> -    template = string.Template(template)
>> -    return template.substitute(data)
>> +    return fmts
>>   
>>   
>>   def main(argv):
>>   
>>       # Parse command line arguments
>>       parser = argparse.ArgumentParser()
>> -    parser.add_argument('-o', dest='output', metavar='file', type=str,
>> +    parser.add_argument('-o', dest='output', metavar='file',
>> +                        type=argparse.FileType('w', encoding='utf-8'), default=sys.stdout,
>>                           help='Output file name. Defaults to standard output if not specified.')
>>       parser.add_argument('input', type=str,
>>                           help='Input file name.')
>> @@ -104,15 +96,13 @@ def main(argv):
>>       formats = yaml.safe_load(data)['formats']
>>       drm_fourcc = DRMFourCC(args.drm_fourcc)
>>   
>> -    data = generate_h(formats, drm_fourcc)
>> -    data = fill_template(args.template, data)
>> +    env = jinja2.Environment()
>> +    template = env.from_string(open(args.template, 'r', encoding='utf-8').read())
>> +    string = template.render({
>> +        'formats': generate_formats(formats, drm_fourcc),
>> +    })
>>   
>> -    if args.output:
>> -        output = open(args.output, 'wb')
>> -        output.write(data.encode('utf-8'))
>> -        output.close()
>> -    else:
>> -        sys.stdout.write(data)
>> +    args.output.write(string)
> 
> This looks reasonable to me.
> 
> All looks ok to me and we already use jinja so :
> 
> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
>>   
>>       return 0
>>   
>> -- 
>> 2.51.0
>>
Laurent Pinchart Sept. 1, 2025, 2:34 p.m. UTC | #3
Hi Barnabás,

Thank you for the patch.

On Mon, Sep 01, 2025 at 11:23:19AM +0200, Barnabás Pőcze wrote:
> Currently the gen-formats.py script can only be used to generate C++
> code because it hard-codes part of the template. Use jinja to fully
> remove any such dependency.
> 
> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> ---
>  include/libcamera/formats.h.in |  4 +++-
>  utils/codegen/gen-formats.py   | 34 ++++++++++++----------------------
>  2 files changed, 15 insertions(+), 23 deletions(-)
> 
> diff --git a/include/libcamera/formats.h.in b/include/libcamera/formats.h.in
> index 6ae7634fe..5ff9c3bf4 100644
> --- a/include/libcamera/formats.h.in
> +++ b/include/libcamera/formats.h.in
> @@ -35,7 +35,9 @@ constexpr uint64_t __mod(unsigned int vendor, unsigned int mod)
>  
>  } /* namespace */
>  
> -${formats}
> +{% for f in formats %}
> +constexpr PixelFormat {{f.name}}(__fourcc({{f.fourcc}}), __mod({{f.mod}}));
> +{%- endfor %}
>  
>  } /* namespace formats */
>  
> diff --git a/utils/codegen/gen-formats.py b/utils/codegen/gen-formats.py
> index 0c0932a5b..872f3fe34 100755
> --- a/utils/codegen/gen-formats.py
> +++ b/utils/codegen/gen-formats.py
> @@ -7,6 +7,7 @@
>  # Generate formats definitions from YAML
>  
>  import argparse
> +import jinja2
>  import re
>  import string
>  import sys
> @@ -52,9 +53,7 @@ class DRMFourCC(object):
>          return self.vendors[vendor], value
>  
>  
> -def generate_h(formats, drm_fourcc):
> -    template = string.Template('constexpr PixelFormat ${name}{ __fourcc(${fourcc}), __mod(${mod}) };')
> -
> +def generate_formats(formats, drm_fourcc):
>      fmts = []
>  
>      for format in formats:
> @@ -73,24 +72,17 @@ def generate_h(formats, drm_fourcc):
>          if mod:
>              data['mod'] = '%u, %u' % drm_fourcc.mod(mod)
>  
> -        fmts.append(template.substitute(data))
> -
> -    return {'formats': '\n'.join(fmts)}
> -
> -
> -def fill_template(template, data):
> +        fmts.append(data)
>  
> -    template = open(template, 'rb').read()
> -    template = template.decode('utf-8')
> -    template = string.Template(template)
> -    return template.substitute(data)
> +    return fmts
>  
>  
>  def main(argv):
>  
>      # Parse command line arguments
>      parser = argparse.ArgumentParser()
> -    parser.add_argument('-o', dest='output', metavar='file', type=str,
> +    parser.add_argument('-o', dest='output', metavar='file',
> +                        type=argparse.FileType('w', encoding='utf-8'), default=sys.stdout,

I like this. Could you send a patch to do the same in the other code
generation scripts ?

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

>                          help='Output file name. Defaults to standard output if not specified.')
>      parser.add_argument('input', type=str,
>                          help='Input file name.')
> @@ -104,15 +96,13 @@ def main(argv):
>      formats = yaml.safe_load(data)['formats']
>      drm_fourcc = DRMFourCC(args.drm_fourcc)
>  
> -    data = generate_h(formats, drm_fourcc)
> -    data = fill_template(args.template, data)
> +    env = jinja2.Environment()
> +    template = env.from_string(open(args.template, 'r', encoding='utf-8').read())
> +    string = template.render({
> +        'formats': generate_formats(formats, drm_fourcc),
> +    })
>  
> -    if args.output:
> -        output = open(args.output, 'wb')
> -        output.write(data.encode('utf-8'))
> -        output.close()
> -    else:
> -        sys.stdout.write(data)
> +    args.output.write(string)
>  
>      return 0
>

Patch
diff mbox series

diff --git a/include/libcamera/formats.h.in b/include/libcamera/formats.h.in
index 6ae7634fe..5ff9c3bf4 100644
--- a/include/libcamera/formats.h.in
+++ b/include/libcamera/formats.h.in
@@ -35,7 +35,9 @@  constexpr uint64_t __mod(unsigned int vendor, unsigned int mod)
 
 } /* namespace */
 
-${formats}
+{% for f in formats %}
+constexpr PixelFormat {{f.name}}(__fourcc({{f.fourcc}}), __mod({{f.mod}}));
+{%- endfor %}
 
 } /* namespace formats */
 
diff --git a/utils/codegen/gen-formats.py b/utils/codegen/gen-formats.py
index 0c0932a5b..872f3fe34 100755
--- a/utils/codegen/gen-formats.py
+++ b/utils/codegen/gen-formats.py
@@ -7,6 +7,7 @@ 
 # Generate formats definitions from YAML
 
 import argparse
+import jinja2
 import re
 import string
 import sys
@@ -52,9 +53,7 @@  class DRMFourCC(object):
         return self.vendors[vendor], value
 
 
-def generate_h(formats, drm_fourcc):
-    template = string.Template('constexpr PixelFormat ${name}{ __fourcc(${fourcc}), __mod(${mod}) };')
-
+def generate_formats(formats, drm_fourcc):
     fmts = []
 
     for format in formats:
@@ -73,24 +72,17 @@  def generate_h(formats, drm_fourcc):
         if mod:
             data['mod'] = '%u, %u' % drm_fourcc.mod(mod)
 
-        fmts.append(template.substitute(data))
-
-    return {'formats': '\n'.join(fmts)}
-
-
-def fill_template(template, data):
+        fmts.append(data)
 
-    template = open(template, 'rb').read()
-    template = template.decode('utf-8')
-    template = string.Template(template)
-    return template.substitute(data)
+    return fmts
 
 
 def main(argv):
 
     # Parse command line arguments
     parser = argparse.ArgumentParser()
-    parser.add_argument('-o', dest='output', metavar='file', type=str,
+    parser.add_argument('-o', dest='output', metavar='file',
+                        type=argparse.FileType('w', encoding='utf-8'), default=sys.stdout,
                         help='Output file name. Defaults to standard output if not specified.')
     parser.add_argument('input', type=str,
                         help='Input file name.')
@@ -104,15 +96,13 @@  def main(argv):
     formats = yaml.safe_load(data)['formats']
     drm_fourcc = DRMFourCC(args.drm_fourcc)
 
-    data = generate_h(formats, drm_fourcc)
-    data = fill_template(args.template, data)
+    env = jinja2.Environment()
+    template = env.from_string(open(args.template, 'r', encoding='utf-8').read())
+    string = template.render({
+        'formats': generate_formats(formats, drm_fourcc),
+    })
 
-    if args.output:
-        output = open(args.output, 'wb')
-        output.write(data.encode('utf-8'))
-        output.close()
-    else:
-        sys.stdout.write(data)
+    args.output.write(string)
 
     return 0