sqlalchemy / mako

Mako Templates for Python
https://www.makotemplates.org
MIT License
353 stars 60 forks source link

render_context makes Mako to escape backslashes #394

Closed marcosps closed 2 weeks ago

marcosps commented 5 months ago

My usecase is to include C file into different files. Imagine the following being difined in a file:

#define debug(param) \
do {                                      \
                   bla bla bla        \
} while (0)

(Imagine that the backslashes above were aligned...)

When the file with the context above is used with <%include file=....\>

It becomes

#define debug(param) do { bla bla bla } while (0) 

Is there a way t prevent Mako to do it? Thanks in advance!

zzzeek commented 5 months ago

it's not pretty but you'd have to do this

from mako.template import Template

tt = r"""
<%! BS='\\' %>
#define debug(param) ${BS}
do {                                      ${BS}
                   bla bla bla        ${BS}
} while (0)
"""

t = Template(tt)

print(t.render())
marcosps commented 5 months ago

it's not pretty but you'd have to do this

from mako.template import Template

tt = r"""
<%! BS='\\' %>
#define debug(param) ${BS}
do {                                      ${BS}
                   bla bla bla        ${BS}
} while (0)
"""

t = Template(tt)

print(t.render())

thanks @zzzeek , but the code that I import is generated by a different tool =/ I believe that things can get even more complicated if I try to massage the text before including it =/

zzzeek commented 5 months ago

you can use a preprocessor function to achieve this

from mako.template import Template

def preproc_slashes(text):
    return r"<%! BS='\\' %>" + text.replace("\\", "${BS}")

tt = r"""#define debug(param) \
do {                                      \
                   bla bla bla        \
} while (0)
"""

t = Template(tt, preprocessor=preproc_slashes)

print(t.render())
marcosps commented 5 months ago

you can use a preprocessor function to achieve this

from mako.template import Template

def preproc_slashes(text):
    return r"<%! BS='\\' %>" + text.replace("\\", "${BS}")

tt = r"""#define debug(param) \
do {                                      \
                   bla bla bla        \
} while (0)
"""

t = Template(tt, preprocessor=preproc_slashes)

print(t.render())

Thanks a lot @zzzeek , this example code work perfectly, but somehow in my usecase I had to add the preprocessor to my TemplateLookup object. Either way it worked for me, thanks a lot!

marcosps commented 2 weeks ago

@zzzeek well, here I am again with one more case to deal when importing C files into Mako :)

I'm not sure if this was the same origin, but I'll post here either way. Let me know if you would like me to open a new bug instead.

I have the following code:

#define ext4_error(sb, fmt, ...)                                        \
        __ext4_error((sb), __func__, __LINE__, false, 0, 0, (fmt),      \
                ##__VA_ARGS__)

And when using the preprocessor above it removed the last ##__VA_ARGS__, breaking the C macro:

#define ext4_error(sb, fmt, ...)                                        \
        __ext4_error((sb), __func__, __LINE__, false, 0, 0, (fmt),      \

Here is a reproducer:

from mako.template import Template                                                                                    

def preproc_slashes(text):                                                                                            
    return r"<%! BS='\\' %>" + text.replace("\\", "${BS}")                                                            

tt = r"""#define ext4_error(sb, fmt, ...)                                        \                                    
        __ext4_error((sb), __func__, __LINE__, false, 0, 0, (fmt),      \                                             
                ##__VA_ARGS__)                                                                                        
"""                                                                                                                   

t = Template(tt, preprocessor=preproc_slashes)                                                                        

print(t.render())

This only happens when the ## is on a new line. Is there a way that I can make sure that Mako imports the code as it is? I'm serioualy thinking to include the file manually instead of using the Mako's <%include> clause. Would that a better approach in this case?

Thanks a lot!

zzzeek commented 2 weeks ago

well ## is Mako's comment syntax. so if you have your preprocessor, you want to replace ## with ${"##"}.

marcosps commented 2 weeks ago

well ## is Mako's comment syntax. so if you have your preprocessor, you want to replace ## with ${"##"}.

It worked! Thanks a lot for the help again!