I use Jinja2 to create a Python class from a template. My template looks like
class {{class_name}}({{base_class_name}}):
def __init__(self, {{ parameters|join(', ') }}):
{{comment}}
super().__init__()
{% for param in parameters%}
self.{{param}} = {{param}}
{%- endfor %}
{# First variant #}
self.parameters1 = {{parameter_list}}
{# Second variant #}
self.parameters2 = {{['self.'] | product(parameters) | map('join') | list}}
And my python script is defined as
from itertools import product
from pathlib import Path
import jinja2
def create_class_from_template():
templates_path = Path(__file__).parent / 'templates'
jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(templates_path))
jinja_env.filters['product'] = product
parameters = ['param1', 'param2', 'param3'] # For first variant
parameter_list = [f'self.{param}' for param in parameters] # For second variant
template_variables = {
'class_name': 'TestClass',
'base_class_name': 'BaseClass',
'comment': '"""My generated class"""',
'parameters': parameters,
'parameter_list': parameter_list
}
template = jinja_env.get_template('class_template.py.jinja2')
my_class = template.render(template_variables)
with open('my_new_class.py', 'w') as file:
file.write(my_class)
create_class_from_template()
Which creates the following python file
class TestClass(BaseClass):
def __init__(self, param1, param2, param3):
"""My generated class"""
super().__init__()
self.param1 = param1
self.param2 = param2
self.param3 = param3
self.parameters1 = ['self.param1', 'self.param2', 'self.param3']
self.parameters2 = ['self.param1', 'self.param2', 'self.param3']
But instead of strings the list should contain the members itself, so that it is self.parameters = [self.param1, self.param2, self.param3]
.
Does anybody have an idea how I could create such a list using Jinja2 and Python?
It can work without changing your script, just make the template like this:
class {{class_name}}({{base_class_name}}):
def __init__(self, {{ parameters|join(', ') }}):
{{comment}}
super().__init__()
{% for param in parameters%}
self.{{param}} = {{param}}
{%- endfor %}
self.parameters = [{% for param in parameters %}self.{{ param }}{%- if not loop.last %}, {% endif %}{% endfor %}]
Slightly neater output as well. And then you only need one template variable (parameters
), you can do the formatting in the template itself.
class TestClass(BaseClass):
def __init__(self, param1, param2, param3):
"""My generated class"""
super().__init__()
self.param1 = param1
self.param2 = param2
self.param3 = param3
self.parameters = [self.param1, self.param2, self.param3]