1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
# (c) 2019 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# CAUTION: This implementation of the collection loader is used by ansible-test.
# Because of this, it must be compatible with all Python versions supported on the controller or remote.
from __future__ import annotations
from . import _to_text
class _EventSource:
def __init__(self):
self._handlers = set()
def __iadd__(self, handler):
if not callable(handler):
raise ValueError('handler must be callable')
self._handlers.add(handler)
return self
def __isub__(self, handler):
try:
self._handlers.remove(handler)
except KeyError:
pass
return self
def _on_exception(self, handler, exc, *args, **kwargs):
# if we return True, we want the caller to re-raise
return True
def fire(self, *args, **kwargs):
for h in self._handlers:
try:
h(*args, **kwargs)
except Exception as ex:
if self._on_exception(h, ex, *args, **kwargs):
raise
class _AnsibleCollectionConfig(type):
def __init__(cls, meta, name, bases):
cls._collection_finder = None
cls._default_collection = None
cls._on_collection_load = _EventSource()
@property
def collection_finder(cls):
return cls._collection_finder
@collection_finder.setter
def collection_finder(cls, value):
if cls._collection_finder:
raise ValueError('an AnsibleCollectionFinder has already been configured')
cls._collection_finder = value
@property
def collection_paths(cls):
cls._require_finder()
return [_to_text(p) for p in cls._collection_finder._n_collection_paths]
@property
def default_collection(cls):
return cls._default_collection
@default_collection.setter
def default_collection(cls, value):
cls._default_collection = value
@property
def on_collection_load(cls):
return cls._on_collection_load
@on_collection_load.setter
def on_collection_load(cls, value):
if value is not cls._on_collection_load:
raise ValueError('on_collection_load is not directly settable (use +=)')
@property
def playbook_paths(cls):
cls._require_finder()
return [_to_text(p) for p in cls._collection_finder._n_playbook_paths]
@playbook_paths.setter
def playbook_paths(cls, value):
cls._require_finder()
cls._collection_finder.set_playbook_paths(value)
def _require_finder(cls):
if not cls._collection_finder:
raise NotImplementedError('an AnsibleCollectionFinder has not been installed in this process')
# concrete class of our metaclass type that defines the class properties we want
class AnsibleCollectionConfig(object, metaclass=_AnsibleCollectionConfig):
pass
|