示例#1
0
    def _parse_envelope_value(
        self,
        name: str,
        envelope: Optional[Envelope] = None,
        parse_fun: Optional[Callable[[Any], Any]] = None,
        instance_lookup_fun: Optional[Callable[...,
                                               Optional[Any]]] = None) -> Any:
        """
        Parse the envelope for the given `name`. If present in the envelope the extracted value will
        be tested / parsed by the given `parse_fun`. If no `parse_fun` is explicitly given, it will
        be determined if this instance provides a `parse_<name>`, `_parse_<name>` or a
        `__parse_<name>`. If yes the function is called; otherwise the value is returned as is.

        If the value is not present in the envelope the current instance will be probed for
        `<name>`, `_<name>` or `__<name>`. If an instance variable is present it will be returned
        unvalidated / unparsed (we assume that happened previously). If no variable is present
        simply `None` will be returned.

        Args:
            name: Name of the attribute to lookup in the envelope / instance.
            envelope: Envelope of the payload.
            parse_fun: Custom function to validate / parse. If not given it will be determined
                automagically.
            instance_lookup_fun: Custom function to perform instance variable lookups.
                If not given a reasonably default will be used.
        """
        validator.is_instance(str, name=name)
        validator.is_instance(dict, allow_none=True, envelope=envelope)
        if parse_fun:
            validator.is_function(parse_fun=parse_fun)
        if instance_lookup_fun:
            validator.is_function(instance_lookup_fun=instance_lookup_fun)

        lookups = cast(
            Dict[str, str],
            utils.make_public_protected_private_attr_lookup(name,
                                                            as_dict=True))

        if envelope is None or name not in envelope:
            return (instance_lookup_fun(name) if instance_lookup_fun
                    is not None else _lookup(self, list(lookups.values()))  # pylint: disable=no-member
                    )

        val = envelope[name]
        try:
            if parse_fun is None:
                public_attr_name = lookups['public']  # pylint: disable=invalid-sequence-index
                fun_base = 'parse_' + public_attr_name
                parse_fun_names = utils.make_public_protected_private_attr_lookup(
                    fun_base)
                parse_fun = _lookup(self, parse_fun_names)
                if parse_fun is None:
                    return val
            return parse_fun(val)
        except (ValueError, TypeError):
            self.logger.exception("Cannot parse value for '%s' from envelope",
                                  name)
            return (instance_lookup_fun(name) if instance_lookup_fun
                    is not None else _lookup(self, list(lookups.values()))  # pylint: disable=no-member
                    )
示例#2
0
def make_public_protected_private_attr_lookup(attr_name: str, as_dict: bool = False) \
        -> Union[Dict[str, str], List[str]]:
    """
    Given an attribute name this function will generate names of public, private and protected
    attribute names. The order is of lookups is always the given attr_name first and then
    descending by visibility (public -> proctected -> private)

    Examples:
        >>> make_public_protected_private_attr_lookup('my_lookup')  # Public attribute name
        ['my_lookup', '_my_lookup', '__my_lookup']
        >>> make_public_protected_private_attr_lookup('_my_lookup')  # Protected attribute name
        ['_my_lookup', 'my_lookup', '__my_lookup']
        >>> make_public_protected_private_attr_lookup('__my_lookup')  # Private attribute name
        ['__my_lookup', 'my_lookup', '_my_lookup']
        >>> l = make_public_protected_private_attr_lookup('_my_lookup', as_dict=True)
        >>> list(l.keys()), list(l.values())
        (['protected', 'public', 'private'], ['_my_lookup', 'my_lookup', '__my_lookup'])

    """
    validator.is_instance(str, lookup_name=attr_name)
    as_dict = try_parse_bool(as_dict, default=False)
    if attr_name.startswith('__'):
        # __lookup, lookup, _lookup
        res = OrderedDict([('private', attr_name), ('public', attr_name[2:]),
                           ('protected', attr_name[1:])])
    elif attr_name.startswith('_'):
        # _lookup, lookup, __lookup
        res = OrderedDict([('protected', attr_name), ('public', attr_name[1:]),
                           ('private', '_' + attr_name)])
    else:
        # lookup, _lookup, __lookup
        res = OrderedDict([('public', attr_name),
                           ('protected', '_' + attr_name),
                           ('private', '__' + attr_name)])
    return res if as_dict else list(res.values())
示例#3
0
    def __init__(self, directory=None, port=2121, user_pwd=None, events=None,
                 max_cons=256, max_cons_ip=5, **kwargs):
        super().__init__(**kwargs)
        self.port = int(port)
        self.max_cons = int(max_cons)
        self.max_cons_ip = int(max_cons_ip)
        validator.is_instance(str, allow_none=True, directory=directory)
        if directory:
            validator.is_directory(directory=directory)
        self.directory = directory
        if not user_pwd:  # No password -> anonymous access
            self.user = None
        elif isinstance(user_pwd, str):
            self.user = user_pwd
            self.password = ''
        elif is_iterable_but_no_str(user_pwd) and user_pwd:  # at least one element
            self.user = user_pwd[0]
            if len(user_pwd) > 1:  # Password too
                self.password = user_pwd[1]
        else:
            raise TypeError("Argument 'user_pwd' is expected to be a str (user) or a tuple of "
                            "user and password.")

        self.events = make_list(events) or copy.copy(self.ALL_EVENTS)
        if self.events:
            validator.subset_of(self.ALL_EVENTS, events=self.events)

        self.server = None
示例#4
0
文件: ml.py 项目: HazardDede/pnp
    def __init__(self,
                 known_faces=None,
                 known_faces_dir=None,
                 unknown_label="Unknown",
                 lazy=False,
                 **kwargs):
        # known_faces -> mapping name -> list of files
        # known_faces_dir -> directory with known faces (filename -> name)
        # unknown_label -> Label for unknown faces
        super().__init__(**kwargs)

        one_not_none(known_faces=known_faces, known_faces_dir=known_faces_dir)
        self.known_faces = known_faces
        validator.is_instance(dict,
                              allow_none=True,
                              known_faces=self.known_faces)
        self.known_faces_dir = known_faces_dir and str(known_faces_dir)
        if self.known_faces_dir:
            validator.is_directory(known_faces_dir=self.known_faces_dir)

        if not lazy:
            self._configure()
        else:
            self.known_names = None
            self.known_encodings = None
            self.face_recognition = None

        self.unknown_label = str(unknown_label)
示例#5
0
文件: mqtt.py 项目: HazardDede/pnp
 def __init__(self, discovery_prefix, component, config, object_id=None, node_id=None, **kwargs):
     super().__init__(**kwargs)
     self.discovery_prefix = str(discovery_prefix)
     validator.one_of(self.SUPPORTED_COMPONENTS, component=str(component))
     self.component = str(component)
     self.object_id = self._parse_object_id(object_id)
     validator.is_instance(dict, config=config)
     self._config = config
     self.node_id = self._parse_node_id(node_id)
     self.configured = {}
示例#6
0
        def _call(self: 'Push',
                  envelope: Optional[Envelope] = None,
                  payload: Payload = None,
                  **kwargs: Any) -> Payload:
            validator.is_instance(Push, self=self)
            parsed = self._parse_envelope_value(value, envelope=envelope)

            new_kwargs = {value: parsed, 'payload': payload}
            if envelope is not None:
                new_kwargs['envelope'] = envelope

            return fun(self, **{**new_kwargs, **kwargs})
示例#7
0
文件: _base.py 项目: HazardDede/pnp
    async def execute(
            self,
            ident: str,
            payload: Payload,
            push: PushModel,
            result_callback: Optional[PushResultCallback] = None) -> None:
        """
        Executes the given push (in an asynchronous context) by passing the specified payload.
        In concurrent environments there might be multiple executions in parallel.
        You may specify an `id` argument to identify related execution steps in the logs.
        Use the `result_callback` when the engine can take care of dependent pushes as well.
        The result and a dependent push will be passed via the callback. If the callback is not
        specified the PushExecute will execute them in a recursive manner.

        Args:
            ident (str): ID to identify related execution steps in the logs
                (makes sense in concurrent environments).
            payload (Any): The payload to pass to the push.
            push (PushModel): The push instance that has to process the payload.
            result_callback (callable): See explanation above.
        """
        validator.is_instance(PushModel, push=push)

        if result_callback and not callable(result_callback):
            self.logger.warning(
                "Result callback is given, but is not a callable. Callback will be ignored."
            )
            result_callback = None

        if push.unwrap and is_iterable_but_no_str(payload):
            # Payload unwrapping
            length = len(payload)
            self.logger.debug("[%s] Unwrapping payload to %s individual items",
                              ident, str(length))
            for item in payload:
                await self._internal(ident, item, push, result_callback)
        else:
            # Standard way
            await self._internal(ident, payload, push, result_callback)
示例#8
0
def parse_envelope(value: str) -> PushFunction:
    """Decorator the parse the given value-key from the envelope. This is but a convenience
    decorator / wrapper for `_parse_envelope_value` of the `PushBase` class."""

    validator.is_instance(str, value=value)

    def _inner(fun: PushFunction) -> PushFunction:
        validator.is_function(fun=fun)

        def _call(self: 'Push',
                  envelope: Optional[Envelope] = None,
                  payload: Payload = None,
                  **kwargs: Any) -> Payload:
            validator.is_instance(Push, self=self)
            parsed = self._parse_envelope_value(value, envelope=envelope)

            new_kwargs = {value: parsed, 'payload': payload}
            if envelope is not None:
                new_kwargs['envelope'] = envelope

            return fun(self, **{**new_kwargs, **kwargs})

        if asyncio.iscoroutinefunction(fun):

            @functools.wraps(fun)
            async def _wrapper(self: 'Push',
                               envelope: Optional[Envelope] = None,
                               payload: Payload = None,
                               **kwargs: Any) -> Payload:
                return await _call(self, envelope, payload, **kwargs)

            return _wrapper

        return functools.wraps(fun)(_call)

    return _inner
示例#9
0
 def _call(self: 'Push', *args: Any, **kwargs: Any) -> Any:
     validator.is_instance(Push, self=self)
     kwargs.pop('envelope', None)
     return fun(self, *args, **kwargs)
示例#10
0
 def _call(self: 'Push', payload: Payload) -> Payload:
     validator.is_instance(Push, self=self)
     envelope, real_payload = self.envelope_payload(payload)
     return fun(self, envelope=envelope, payload=real_payload)
示例#11
0
def load_plugin(plugin_path: str,
                plugin_type: Union[type, str],
                instantiate: bool = True,
                **kwargs: Any) -> Union[Plugin, Callable[..., Any]]:
    """
    Loads a plugin by using a fully qualified identifier (<module_path>.<class_name>,
    e.g. pnp.plugins.pull.simple.Repeat).

    Args:
        plugin_path: Fully qualified path to plugin path.
        plugin_type: Base class the plugin has to extend / inherit from.
        instantiate: If True the class will be instantiated by passing the given **kwargs.
            Otherwise the class (not an object) is returned.
        **kwargs: Plugin arguments.

    Returns:
        If everything went fine an instantiated plugin is returned.
        Multiple things can go wrong:
        - Module not found (NamespaceNotFoundError)
        - Class not found (ClassNotFoundError)
        - Instantiation error (InvocationError)
        - Wrong plugin base type (PluginTypeError)
    """
    validator.is_instance(str, plugin_path=plugin_path)
    validator.is_instance(type, str, plugin_type=plugin_type)
    if isinstance(plugin_type, str) and plugin_type != 'callable':
        raise ValueError(
            "When 'plugin_type' is str, the only allowed value is callable")

    k = plugin_path.rfind('.')
    if k > -1:
        # Namespace = everything before the last '.'
        namespace = plugin_path[:k]
        # Class name = everything after the last '.'
        clazz_name = plugin_path[k + 1:]
    else:
        namespace = 'builtins'
        clazz_name = plugin_path

    try:
        loaded_module = import_module(namespace)
        clazz = getattr(loaded_module, clazz_name)

        if isinstance(plugin_type, str) and plugin_type == 'callable':
            if not callable(clazz):
                raise PluginTypeError(
                    "The plugin is requested to be a callable, but it is not.")
        else:
            if not issubclass(clazz, cast(type, plugin_type)):
                raise PluginTypeError(
                    "The plugin is requested to inherit from '{}', but it does not."
                    .format(plugin_type))

        return cast(Plugin, clazz(
            **kwargs)) if instantiate else cast(Callable[..., Any], clazz)
    except AttributeError:
        raise ClassNotFoundError(
            'Class {} was not found in namespace {}'.format(
                clazz_name, namespace)) from None
    except ImportError:
        raise NamespaceNotFoundError(
            "Namespace '{}' not found".format(namespace)) from None
    except TypeError as terr:
        raise InvocationError(
            "Invoked constructor from class '{}' in namespace '{}' failed".
            format(clazz_name, namespace)) from terr
示例#12
0
 def __init__(self, delta: timedelta):
     self.throttle_period = delta
     validator.is_instance(timedelta, delta=delta)
     self.time_of_last_call = datetime.min