def assert_not_registered(self, cmd_or_alias: str, context: VerediContext) -> None: ''' Raises a CommandRegisterError if `cmd_or_alias` is already registered as a command or an alias. ''' existing, _ = self.get(cmd_or_alias) if not existing: return kwargs = log.incr_stack_level(None) msg = ("A command named '{}' already registered '{}'; cannot " "register another. command: {}").format(existing.name, cmd_or_alias, existing) error = CommandRegisterError(msg, None, context=context, data={ 'existing': existing, 'existing.name': existing.name, 'cmd_or_alias': cmd_or_alias, }) raise self._log_exception(error, msg, context=context, **kwargs)
def exception(klass: Type['config'], context: Optional['VerediContext'], msg: Optional[str], *args: Any, error_data: Optional[Mapping[Any, Any]] = None, **kwargs: Any) -> None: ''' Calls log.exception() to raise a ConfigError with message built from msg, args, kwargs and with supplied context. NOTE: If no context is supplied, WILL NOT LOG ANY! Provide config.make_config_context() if you are using it as your default! Sets stack level one more than usual so that caller of this should be the stacktrace of the exception. If optional `error_data` is not None, it will be supplied to the created ConfigError as the `data` parameter in the constructor. ''' kwargs = log.incr_stack_level(kwargs) # If we raised instead of returned, we could add an extra stacklevel to # get the log back to whoever called us... # amount=2) # Let a generic ConfigError be made. return log.exception( ConfigError, msg, *args, **kwargs, error_data=error_data, context=context)
def debug(self, msg: str, *args: Any, **kwargs: Any) -> None: ''' Debug logs go through our callback if we have it. Otherwise just use log.debug. ''' kwargs = log.incr_stack_level(kwargs) call = self._debug_fn if self._debug_fn else log.debug call(msg, *args, **kwargs)
def next(self, value: CurrNextT) -> None: ''' Sets next value. ''' if self._freeze_next: kwargs = log.incr_stack_level(None) log.info( f"Currently next is frozen at {self._next}; " f"cannot set next value to {value}.", **kwargs) return self._next = value
def debug(self, msg: str, *args: Any, **kwargs: Any) -> None: ''' Debug logs if our DebugFlag has the proper bits set for Mediator debugging. ''' if (self._debug and self._debug.any(DebugFlag.MEDIATOR_BASE, DebugFlag.MEDIATOR_CLIENT)): msg = f"{self.name}: " + msg kwargs = log.incr_stack_level(kwargs) self._log_data_processing(self.dotted, msg, *args, **kwargs, log_minimum=log.Level.DEBUG)
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)
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)