Exemplo n.º 1
0
def to_log(log_name: str) -> None:
    '''
    Log background out at a level that will likely get printed.
    '''
    from veredi.base.strings import pretty
    output = pretty.indented(background._CONTEXT, sort=True)
    # TODO [2020-06-28]: Log function for 'always log this' that isn't
    # "CRITICAL ERROR OMG!!!"?
    log.critical(f'{_LOG_TITLE} (requested by {log_name}):\n' + output)
Exemplo n.º 2
0
    def __str__(self):
        output = f"{self.message}"
        if self.cause:
            output += f" from {self.cause}"
        if self.context:
            output += f" with context {self.context}"
        if self.data:
            output += "\nAdditional Error Data:\n"
            output += pretty.indented(self.data)

        return output
Exemplo n.º 3
0
    def _log(self,
             context:      InputContext,
             level:        log.Level,
             entity:       Entity,
             command_name: str,
             command_safe: str,
             message:      str,
             *args:        Any,
             **kwargs:     Any) -> None:
        '''
        Format command info from context into standard command log message,
        then append message and call log.at_level().

        Log's stack level (for method/class auto-print by logger) should be at
        level of caller of this function.
        '''
        ident = entity.get(IdentityComponent)
        ent_name = ident.log_name
        cmd_info = {
            'source': {
                'name': ent_name,
                'group': ident.group,
                'controller': ident.controller,
                # todo: controller entity id, user id
            },
            'name': command_name,
            'input': command_safe,
        }

        fmt_pre = "- command: '{}' invoked by '{}' - "
        msg_pre = fmt_pre.format(command_name, ent_name)
        msg_post = '\n' + pretty.indented(cmd_info)

        log_fmt = msg_pre + message + '{msg_post}'
        kwargs['msg_post'] = msg_post
        log.incr_stack_level(kwargs)
        self._log_at_level(level, log_fmt, *args, **kwargs)
Exemplo n.º 4
0
 def _pretty(self):
     from veredi.base.strings import pretty
     from pprint import pformat
     return pretty.indented(f"{self.klass}:\n" + pformat(self._get()))
Exemplo n.º 5
0
 def _pretty(self):
     from veredi.base.strings import pretty
     return (f"{self.__str_name__()}:\n" +
             f"  data:  {self._str_data()}\n" + "  context:\n" +
             pretty.indented(self._context._pretty(), indent_amount=4))
Exemplo n.º 6
0
 def _pretty(self):
     from veredi.base.strings import pretty
     return (f"{self.__str_name__()}:\n  context:\n" +
             pretty.indented(self._context._pretty(), indent=4))
Exemplo n.º 7
0
def to_str() -> str:
    from veredi.base.strings import pretty
    return "Veredi Backgroud Context:\n" + pretty.indented(_CONTEXT)
Exemplo n.º 8
0
    def add(self, cls_or_func: 'RegisterType',
            *dotted_label: label.LabelInput) -> None:
        '''
        This function does the actual registration.
        '''
        # Ignored?
        if self.ignored(cls_or_func):
            msg = (f"{cls_or_func} is in our set of ignored "
                   "classes/functions that should not be registered.")
            error = RegistryError(msg,
                                  data={
                                      'registree': cls_or_func,
                                      'dotted': label.normalize(dotted_label),
                                      'ignored': self._ignore,
                                  })
            raise log.exception(error, msg)

        # Do any initial steps.
        dotted_list = label.regularize(*dotted_label)
        if not self._init_register(cls_or_func, dotted_list):
            # Totally ignore if not successful. _init_register() should do
            # all the erroring itself.
            return

        # Pull final key off of list so we don't make too many
        # dictionaries.
        name = str(cls_or_func)
        try:
            # Final key where the registration will actually be stored.
            leaf_key = dotted_list[-1]
        except IndexError as error:
            kwargs = log.incr_stack_level(None)
            raise log.exception(
                RegistryError, "Need to know what to register this ({}) as. "
                "E.g. @register('jeff', 'geoff'). Got no dotted_list: {}",
                name, dotted_list, **kwargs) from error

        # Our register - full info saved here.
        registry_our = self._registry

        # Background register - just names saved here.
        registry_bg = background.registry.registry(self.dotted)

        # ------------------------------
        # Get reg dicts to the leaf.
        # ------------------------------

        length = len(dotted_list)
        # -1 as we've got our config name already from that final
        # dotted_list entry.
        for i in range(length - 1):
            # Walk down into both dicts, making new empty sub-entries as
            # necessary.
            registry_our = registry_our.setdefault(dotted_list[i], {})
            registry_bg = registry_bg.setdefault(dotted_list[i], {})

        # ------------------------------
        # Register (warn if occupied).
        # ------------------------------

        # Helpful messages - but registering either way.
        try:
            if leaf_key in registry_our:
                if background.testing.get_unit_testing():
                    msg = ("Something was already registered under this "
                           f"registry_our key... keys: {dotted_list}, "
                           f"replacing {str(registry_our[leaf_key])}' with "
                           f"this '{name}'.")
                    error = KeyError(leaf_key, msg, cls_or_func)
                    log.exception(error, None, msg, stacklevel=3)
                else:
                    log.warning(
                        "Something was already registered under this "
                        "registry_our key... keys: {}, replacing "
                        "'{}' with this '{}'",
                        dotted_list,
                        str(registry_our[leaf_key]),
                        name,
                        stacklevel=3)
            else:
                log.debug("Registered: keys: {}, value '{}'",
                          dotted_list,
                          name,
                          stacklevel=3)
        except TypeError as error:
            msg = (f"{self.klass}.add(): Our "
                   "'registry_our' dict is the incorrect type? Expected "
                   "something that can deal with 'in' operator. Have: "
                   f"{type(registry_our)} -> {registry_our}. Trying to "
                   f"register {cls_or_func} at "
                   f"'{label.normalize(dotted_list)}'. "
                   "Registry: \n{}")
            from veredi.base.strings import pretty
            log.exception(error, msg, pretty.indented(self._registry))
            # Reraise it. Just want more info.
            raise

        # Register cls/func to our registry, save some info to our
        # background registry.
        self._register(cls_or_func, dotted_list, leaf_key, registry_our,
                       registry_bg)

        # ------------------------------
        # Finalize (if desired).
        # ------------------------------
        self._finalize_register(cls_or_func, dotted_list, registry_our,
                                registry_bg)
Exemplo n.º 9
0
    def get(
        self,
        data: Optional[EncodedEither],
        dotted: Optional[str] = None,
        data_type: Optional[Type[Encodable]] = None,
        error_squelch: bool = False,
        fallback: Optional[Type[Encodable]] = None,
    ) -> Optional[Type[Encodable]]:
        '''
        Get the registered Encodable that this `data` can maybe be decoded to,
        if any of our registered classes match `dotted` field in data, or
        claim() the `data`.

        If `data` is None, returns None.

        If `dotted` is supplied, try to get that Encodable from our registry.
        Use it or raise RegistryError if not found.

        If `data_type` is supplied, will restrict search for registered
        Encodable to just that class or its subclasses.

        `error_squelch` will only raise the exception, instead of raising it
        through log.exception().

        If nothing registered fits `data`:
          - If the `fallback` keyword arg is supplied, return that.
          - Else raise a ValueError.
        '''
        # None decodes to None.
        if data is None:
            return None

        self._log_debug(f"EncodableRegistry.get: data: {type(data)}, "
                        f"dotted: {dotted}, data_type: {data_type}")

        registree = None

        # ---
        # Too simple?
        # ---
        if isinstance(data, (str, *numbers.NumberTypesTuple)):
            self._log_debug(
                "EncodableRegistry.get: Shouldn't be asking the "
                "registry for registered class for simple data types. "
                f"data: {type(data)}, "
                f"dotted: {dotted}, data_type: {data_type}")
            return None

        # ---
        # Use dotted name?
        # ---
        if dotted:
            registree = self.get_by_dotted(dotted, None)

        # ---
        # Search for registered Encodable.
        # ---
        else:
            registry = self._registry
            data_dotted = label.from_map(data, error_squelch=True)
            if data_dotted:
                registree = self._search(registry,
                                         data_dotted,
                                         data,
                                         data_type=data_type)

        # ---
        # Did we find the correct registree?
        # ---
        if registree:
            # Find by claim?
            claiming, _, _ = registree.claim(data)
            if claiming:
                return registree
            else:
                self._log_debug(
                    f"EncodableRegistry.get: Found registree for data, "
                    "but registree will not claim it. "
                    f"registree: {registree}, data: {type(data)}, "
                    f"dotted: {dotted}, data_type: {data_type}")

        # ---
        # Not Found: Fallback if provided?
        # ---
        if fallback:
            return fallback

        # ---
        # No Fallback: Error out.
        # ---
        msg = (f"{self.klass}: "
               "No registered Encodable found for "
               f"data. data_dotted: {data_dotted}")
        extra = (", \n" "registry:\n" "{}\n\n" "data:\n" "{}\n\n")
        error = ValueError(msg, data, registree)
        if error_squelch:
            raise error
        raise self._log_exception(error, msg + extra,
                                  pretty.indented(registry),
                                  pretty.indented(data))