mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-22 12:50:22 -07:00
Add a CLIArgs Singleton class that will hold the parse cli arguments
This commit is contained in:
parent
5844c8c7f0
commit
c18da65089
4 changed files with 265 additions and 3 deletions
83
lib/ansible/arguments.py
Normal file
83
lib/ansible/arguments.py
Normal file
|
@ -0,0 +1,83 @@
|
|||
# Copyright: (c) 2018, Toshio Kuratomi <tkuratomi@ansible.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
"""
|
||||
Hold command line arguments for use in other modules
|
||||
"""
|
||||
|
||||
from abc import ABCMeta
|
||||
|
||||
from ansible.module_utils.common._collections_compat import (Container, Mapping, Sequence, Set)
|
||||
from ansible.module_utils.common.collections import ImmutableDict
|
||||
from ansible.module_utils.six import add_metaclass, binary_type, text_type
|
||||
from ansible.utils.singleton import Singleton
|
||||
|
||||
|
||||
def _make_immutable(obj):
|
||||
"""Recursively convert a container and objects inside of it into immutable data types"""
|
||||
if isinstance(obj, (text_type, binary_type)):
|
||||
# Strings first because they are also sequences
|
||||
return obj
|
||||
elif isinstance(obj, Mapping):
|
||||
temp_dict = {}
|
||||
for key, value in obj.items():
|
||||
if isinstance(value, Container):
|
||||
temp_dict[key] = _make_immutable(value)
|
||||
else:
|
||||
temp_dict[key] = value
|
||||
return ImmutableDict(temp_dict)
|
||||
elif isinstance(obj, Set):
|
||||
temp_set = set()
|
||||
for value in obj:
|
||||
if isinstance(value, Container):
|
||||
temp_set.add(_make_immutable(value))
|
||||
else:
|
||||
temp_set.add(value)
|
||||
return frozenset(temp_set)
|
||||
elif isinstance(obj, Sequence):
|
||||
temp_sequence = []
|
||||
for value in obj:
|
||||
if isinstance(value, Container):
|
||||
temp_sequence.append(_make_immutable(value))
|
||||
else:
|
||||
temp_sequence.append(value)
|
||||
return tuple(temp_sequence)
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
class _ABCSingleton(Singleton, ABCMeta):
|
||||
"""
|
||||
Combine ABCMeta based classes with Singleton based classes
|
||||
|
||||
Combine Singleton and ABCMeta so we have a metaclass that unambiguously knows which can override
|
||||
the other. Useful for making new types of containers which are also Singletons.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class CLIArgs(ImmutableDict):
|
||||
"""Hold a parsed copy of cli arguments"""
|
||||
def __init__(self, mapping):
|
||||
toplevel = {}
|
||||
for key, value in mapping.items():
|
||||
toplevel[key] = _make_immutable(value)
|
||||
super(CLIArgs, self).__init__(toplevel)
|
||||
|
||||
@classmethod
|
||||
def from_options(cls, options):
|
||||
return cls(vars(options))
|
||||
|
||||
|
||||
@add_metaclass(_ABCSingleton)
|
||||
class GlobalCLIArgs(CLIArgs):
|
||||
"""
|
||||
Globally hold a parsed copy of cli arguments.
|
||||
|
||||
Only one of these exist per program as it is for global context
|
||||
"""
|
||||
pass
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright (c), Sviatoslav Sydorenko <ssydoren@redhat.com> 2018
|
||||
# Copyright: (c) 2018, Sviatoslav Sydorenko <ssydoren@redhat.com>
|
||||
# Copyright: (c) 2018, Ansible Project
|
||||
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
|
||||
"""Collection of low-level utility functions."""
|
||||
|
||||
|
@ -7,7 +8,52 @@ __metaclass__ = type
|
|||
|
||||
|
||||
from ansible.module_utils.six import binary_type, text_type
|
||||
from ansible.module_utils.common._collections_compat import Sequence
|
||||
from ansible.module_utils.common._collections_compat import Hashable, Mapping, Sequence
|
||||
|
||||
|
||||
class ImmutableDict(Hashable, Mapping):
|
||||
"""Dictionary that cannot be updated"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._store = dict(*args, **kwargs)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self._store[key]
|
||||
|
||||
def __iter__(self):
|
||||
return self._store.__iter__()
|
||||
|
||||
def __len__(self):
|
||||
return self._store.__len__()
|
||||
|
||||
def __hash__(self):
|
||||
return hash(frozenset(self.items()))
|
||||
|
||||
def __repr__(self):
|
||||
return 'ImmutableDict({0})'.format(repr(self._store))
|
||||
|
||||
def union(self, overriding_mapping):
|
||||
"""
|
||||
Create an ImmutableDict as a combination of the original and overriding_mapping
|
||||
|
||||
:arg overriding_mapping: A Mapping of replacement and additional items
|
||||
:return: A copy of the ImmutableDict with key-value pairs from the overriding_mapping added
|
||||
|
||||
If any of the keys in overriding_mapping are already present in the original ImmutableDict,
|
||||
the overriding_mapping item replaces the one in the original ImmutableDict.
|
||||
"""
|
||||
return ImmutableDict(self._store, **overriding_mapping)
|
||||
|
||||
def difference(self, subtractive_iterable):
|
||||
"""
|
||||
Create an ImmutableDict as a combination of the original minus keys in subtractive_iterable
|
||||
|
||||
:arg subtractive_iterable: Any iterable containing keys that should not be present in the
|
||||
new ImmutableDict
|
||||
:return: A copy of the ImmutableDict with keys from the subtractive_iterable removed
|
||||
"""
|
||||
remove_keys = frozenset(subtractive_iterable)
|
||||
keys = (k for k in self._store.keys() if k not in remove_keys)
|
||||
return ImmutableDict((k, self._store[k]) for k in keys)
|
||||
|
||||
|
||||
def is_string(seq):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue