Hello,
This is my first time posting here. Recently I came across a use case while working with AWS where I needed to reduce a sequence of dictionaries into a list of string and filter out entries based on whether or not the value of one of their attributes was in a given list of values.
For example, I had a sequence of dictionaries like this:
"results": [ { "group_id": "sg-6db69609", "item": { "name": "SSH" } }, { "group_id": "sg-6eb6960a", "item": { "name": "Ping" } }, { "group_id": "sg-75b69611", "item": { "name": "Http" } } ]
And I wanted to convert it to a list of strings using the “group_id” attribute only for entries whose “name” attributes were part of the list [“SSH”, “Http”]. Currently there is no such filter that can accomplish the filtering part. The closest one was “selectattr” but there were no built-in jinja tests that could do a check such as “value in list”. Also, it is my understanding that there is currently no way to add to these tests like you can with filter plugins.
So I decided to add my own filter that takes in the path of a dictionary attribute (ie. “item.name”) and a list of values that the attribute needs to be included in (ie. [“SSH”, “Http”]).
The final call to get the list of strings ended up looking like this:
`
{{ results | attrinlist(“item.name”, [‘SSH’, ‘Http’]) | map(attribute=‘group_id’) | list }}
`
Anyways, just wanted to put this out there to see if it’s something that would make sense making a pull request for to perhaps include it in the core.py file as one of the filter_plugins. Here is the python code that I wrote for this filter. Also, please keep in mind that this is the first time that I’ve written any serious amount of Python so excuse any irregularities or incorrectness in style, syntax, etc. I’m open to improving it of course. Here is the source code"
`
author = ‘luis@escala.io’
class FilterModule(object):
def filters(self):
return {
‘attrinlist’: self.attr_in_list,
}
Returns a new seq of items whose attributes matched any of the elements in the match_list.
def attr_in_list(self, seq, path, match_list):
try:
path = str(path) # Path must be a string.
except UnicodeError:
raise
else:
for item in seq:
if self.matches_any_in_list(path, item, match_list):
yield item
def matches_any_in_list(self, path, mapping, match_list):
try:
value = self.getattrd(mapping, path)
except AttributeError:
raise
else:
if value in match_list:
return True
else:
return False
Uses reduce to get to attributes separated by a “.” in a nested dictionary.
def getattrd(self, obj, name):
try:
return reduce(dict.get, name.split(‘.’), obj)
except AttributeError, e:
raise
`