3

I have a string interpolation issue which I am not sure how to get it straight. Much appreciate any help towards solving this.

Abstract: I have a string template that composes an email body. This string template has both static and dynamic contents. The aim is to fill all dynamic parts of the template with context-specific values that will be supplied with the help of a dictionary.

Question: If you look at the code and output, I am able to extract the Key/Value from the dictionary (first and second print output). However, when the Values become collection type such as list or tuple, I have trouble in extracting them; especially the dynamic part of the text is getting embedded with the [ ] or ( )(third print output).

Is it possible to avoid [ ] or ( ) constructs from the output ? I would prefer the output as

'foo', 'bar'

instead of

['foo', 'bar']

import string

values = {'dynamic': 'foo'}

t = string.Template("""
Static contents        : $dynamic
More static contents.
""")

print('Body:', t.substitute(values))

values = {'dynamic': 'foo, bar'}

print('Body:', t.substitute(values))

values = {'dynamic': ['foo', 'bar']}

print('Body:', t.substitute(values))

enter image description here

Note: Given logic and example only represent the idea of how I am injecting one dynamic content. In reality, I have more than one dynamic variables to be filled. Something like what Mail Merge does in Microsoft Word. E.g:

values = {'surname': 'xxx',
'email':'something@email.com',
'title':'Mr',
'reference':'xxxxx'
'contacts':['a','b','c']
}
S.N
  • 4,910
  • 5
  • 31
  • 51
  • It's up to you to know the type of value stored in the dictionary and to convert them to the desired string before using `t.substitute`. – chepner Nov 08 '19 at 16:08
  • @Error-SyntacticalRemorse, Thanks and thread is updated to be more explicit. – S.N Nov 08 '19 at 16:11

1 Answers1

1

I don't have complete grasp over what exactly you want but instead of using templates why not use regular strings with string formatting?

For Example:

t = """
Static contents : {dynamic}
More static contents.
"""

values = {
  'str': 'foo, bar',
  'dict': {'test': 'foo'},
  'list': ['foo', 'bar'],
  'list2': ["'foo'", "'bar'"],
}

print('Body:', t.format(dynamic=values['str']))
print('Body:', t.format(dynamic=', '.join(values['dict'].values())))

print('Body:', t.format(dynamic=str(values['list'])[1:-1]))
# OR (the less exception prone way)
print('Body:', t.format(dynamic=', '.join(values['list2'])))

Output:

Body:
Static contents : foo, bar
More static contents.

Body:
Static contents : foo, bar2
More static contents.

Body:
Static contents : 'foo', 'bar'
More static contents.

Body:
Static contents : 'foo', 'bar'
More static contents.
  • Thanks you and much appropriated. Template is the option which I am aware that can handle my case better. The original idea is to have a email template with multiple placeholders and these place holders will be filled with values in run time. In concise, you can it as what Microsoft word mail merge does. Your approach definitely work if I were to have a single placeholder. But in reality there are more placeholders in my template. – S.N Nov 08 '19 at 16:19
  • Gotcha, everything in the answer above still works with `string.Template`. Just swap the format calls for substitute calls. That being said if you are doing mail merge and advanced templates I personally would still stick with format strings as they are more powerful. That being said templates are designed to be more user friendly. You will get a lot more power with formatting. [Read this answer](https://stackoverflow.com/a/11630449/8150685). Formatting can do any number of place holders by keyword or position. And it is done at runtime. – Error - Syntactical Remorse Nov 08 '19 at 16:23
  • I am latecomer to the party and it an existing python code. But I will try it and I completely with you when it comes to format string. – S.N Nov 08 '19 at 16:35
  • As there is no support yet on template, i am going ahead with f-string with some iterators. Thanks for your comments. I am accepting this as answer since your code might be useful to other who has similar issues and prefer the proposed format. – S.N Nov 20 '19 at 11:45
  • My answer should work for templates. Just instead of using `t.format(...)` use `t.substitute(...)`. – Error - Syntactical Remorse Nov 20 '19 at 14:46