# -*- coding: utf-8 -*- # Copyright (c) 2021, Remy Keil # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later from __future__ import (absolute_import, division, print_function) __metaclass__ = type DOCUMENTATION = ''' name: counter short_description: Counts hashable elements in a sequence version_added: 4.3.0 author: Rémy Keil (@keilr) description: - Counts hashable elements in a sequence. options: _input: description: A sequence. type: list elements: any required: true ''' EXAMPLES = ''' - name: Count occurrences ansible.builtin.debug: msg: >- {{ [1, 'a', 2, 2, 'a', 'b', 'a'] | community.general.counter }} # Produces: {1: 1, 'a': 3, 2: 2, 'b': 1} ''' RETURN = ''' _value: description: A dictionary with the elements of the sequence as keys, and their number of occurrences in the sequence as values. type: dictionary ''' from ansible.errors import AnsibleFilterError from ansible.module_utils.common._collections_compat import Sequence from collections import Counter def counter(sequence): ''' Count elements in a sequence. Returns dict with count result. ''' if not isinstance(sequence, Sequence): raise AnsibleFilterError('Argument for community.general.counter must be a sequence (string or list). %s is %s' % (sequence, type(sequence))) try: result = dict(Counter(sequence)) except TypeError as e: raise AnsibleFilterError( "community.general.counter needs a sequence with hashable elements (int, float or str) - %s" % (e) ) return result class FilterModule(object): ''' Ansible counter jinja2 filters ''' def filters(self): filters = { 'counter': counter, } return filters