def _determine_color_from_level(self, level): """Determine the color to be used based on the level of the logger""" if level is None or level not in Default().level_number: raise InvalidLevel(level) return Default().color_level_map.get(level, None)
def _check_format(self, format_passed, file_format): """Check the format that needs to be used. If the `format` passed is not None, use it. If the `file_format` is not None, use it, else use the `format` for the same. If `format` and `file_format` are not passed, use the default formats. """ format_valid = bool(format_passed) file_format_valid = bool(file_format) if format_valid: if not file_format_valid: file_format = format_passed else: pass elif not format_valid: format_passed = Default().console_format if not file_format_valid: file_format = Default().file_format else: pass self._console_format = format_passed self._file_format = file_format
def _get_level(self, level_no: int): """Get the level info from the passed level""" level_info = Default().level_number if level_no not in list(level_info.values()): raise Exception("{}: Not a valid level".format(level_no)) return { 'levelno': level_no, 'levelname': [key for (key, value) in level_info.items() if value == level_no][0] }
def _check_logfile(self, log_path): """ Check if the passed logfile path is present. If not present then create it. """ # If the log_file path is not passed, disable the # logging to file if log_path is None: self._disable_file = True return log_path # If it is passed, make it a Path object log_path = Path(log_path).expanduser() # Check if the file is a dir # If it is, then append the file name to the log # path and continue if log_path.is_dir(): log_path = log_path.joinpath(Default().log_file_name) if not log_path.exists(): # Below check is important if the passed log path # is a file name inside some directory if not log_path.parent.exists(): os.makedirs(log_path.parent) f = open(log_path, "w") f.close() return str(log_path)
def _extract_level(self, passed_level: str): """Extract the passed level. If the passed_level is None, then set it to the default level. Else, make sure that the passed level is valid and accordingly return the level in int. """ level_map = Default().level_number # If level is not passed if passed_level is None: return level_map["INFO"] # If it is passed, make sure it's valid if passed_level not in list(level_map.keys()): raise InvalidLevel(passed_level) self._passed_level = passed_level return level_map[passed_level]
def __init__(self, stream: TextIOWrapper, level: str = None, format: str = None, disabled: bool = False): self._passed_level = None self.stream = self._extract_stream(stream) self._level = self._extract_level(level) self._format = Default().file_format if format is None else format self._disabled = disabled
def update_format_console(self, format): """Update the format for all the non file instances This is useful if an app requires different formats for file and console and both are updated throug one instance. """ valid_names = Default().valid_stdout_names for stream in self._streams: if stream.stream_name not in valid_names: stream.format = format
def _disable_file_streams(self): """Disable the file streams. We will check if the streams are files or standard, based on that, we can disable the streams accordingly. This won't have any effect if the log_file path was not passed during init. """ valid_names = Default().valid_stdout_names for stream in self._streams: if stream.stream_name not in valid_names: stream.disabled = self._disable_file
def get_log_file(self): """Get the log file that is being written to. This is just to support backward functionality for ytmdl. We cannot just return the log file since a lot of instances would be sharing one file and the file will be updated from the final master instance. We will have to get the file through the available streams. """ return [ stream for stream in self._streams if stream.stream_name not in Default().valid_stdout_names ]
def update_format(self, format, file_format=None): """Update the format of all the instances. We need to update the instances seperately based on the type of the stream. """ valid_stdout_names = Default().valid_stdout_names file_format = format if file_format is None else file_format for stream in self._streams: if stream.stream_name in valid_stdout_names: # Probably a console format stream.format = format else: # Probably a file stream stream.format = file_format
def update_file_level(self, level): """ Update the level of all the file streams. This will update the log level of all the file streams. """ # First check if the passed level is present in the supported ones if level not in self._level_number: raise InvalidLevel(level) valid_names = Default().valid_stdout_names # Update the level for only stdout outputs for stream in self._streams: if stream.stream_name not in valid_names: stream.level = self._level_number[level]
def write(self, message, calling_level, frame, logger_name): """Write the message to the stream by making sure the calling level is above or equal to the level """ if calling_level < self._level or self._disabled: return False _formatted_out = self._make_format(message, calling_level, frame, logger_name) params = {"end": ""} if self.stream.name not in Default().valid_stdout_names: # Add the stream since it won't be stdout params["file"] = self.stream print(_formatted_out, **params) return True
def __init__(self, name, **kwargs): self.name = name self._level_number = Default().level_number self._passed_level = kwargs.get("level", "INFO") self._passed_file_level = kwargs.get("file_level", "DEBUG") self.level = self._level_number[self._passed_level] self._file_level = self._level_number[self._passed_file_level] self._disable_file = kwargs.get("disable_file", False) self._log_file = self._check_logfile(kwargs.get("log_path", None)) self._check_format(kwargs.get("format", None), kwargs.get("file_format", None)) self._init_default_streams() # Update all instances, if asked to if kwargs.get("update_all", False): self.update_format(self._console_format) self.update_disable_file(self._disable_file) self.update_level(self._passed_level) self._instances.append(self)
def _build_message(self, level): """Build a message to show the user""" message = "{level}: is an invalid level."\ " Expected one of these: {all_levels}" return message.format(level=level, all_levels=list(Default().level_number.keys()))