fire2a
Hello World 👋🌎 This is Forest Fire Analytics 🌲🔥ðŸ§
When developing fire2a, AVOID writing code like this:
from fire2a.module import function
Use this instead:
from .module import function
UNTIL WE CAN DISTRIBUTE ON PYPI!!
This is fire2a-lib distribution, fire2a package docstring More info on:
fire2a.github.io/fire2a-lib
fire2a.github.io/docs
www.fire2a.com
1#!python3 2"""Hello World 👋🌎 3This is Forest Fire Analytics 🌲🔥🧠4 5When developing fire2a, AVOID writing code like this: 6 7 from fire2a.module import function 8 9Use this instead: 10 11 from .module import function 12 13UNTIL WE CAN DISTRIBUTE ON PYPI!! 14 15This is fire2a-lib distribution, fire2a package docstring 16More info on: 17 18 fire2a.github.io/fire2a-lib 19 fire2a.github.io/docs 20 www.fire2a.com 21""" # fmt: skip 22__author__ = "Fernando Badilla" 23__revision__ = "$Format:%H$" 24 25import logging 26from importlib.metadata import PackageNotFoundError, distribution 27from pathlib import Path 28from typing import Any, Dict, List, Tuple, Union 29 30logger = logging.getLogger(__name__) 31 32try: 33 __version__ = distribution("fire2a-lib").version 34 version_from = "importlib" 35except PackageNotFoundError: 36 if (Path(__file__).parent / "_version.py").exists(): 37 from ._version import __version__ 38 39 version_from = "_version.py" 40 else: 41 __version__ = "0.0.0" 42 version_from = "fallback" 43 44# logger.warning("%s Package version: %s, from %s", __name__, __version__, version_from) 45 46 47 48def setup_logger(name: str = __name__, verbosity: int = 0, logfile: Path = None): 49 r"""Capture the logger and setup name, verbosity, stream handler & rotating logfile if provided. 50 Args: 51 name (str, optional): Name of the logger. Defaults to \__name __ 52 verbosity (str | int): Verbosity level, implemented, WARNING:1, INFO:2 (default), or DEBUG:3 53 logfile (Path, optional): Create a -rotated- logfile (5 files, 25MB each). 54 Returns: 55 logger (Logger): All code in this pkg uses logger.info("..."), logger.debug, etc. 56 57 ## Developers implementing their own logger 58 * All fire2a modules uses `logger = logging.getLogger(__name__)` 59 60 # Regular Usage Guideline 61 logging.critical("Something went wrong, exception info?", exc_info=True) 62 logging.error("Something went wrong, but we keep going?") 63 logging.warning("Default message level") 64 logging.info("Something planned happened") 65 logging.debug("Details of the planned thing that happened") 66 print("Normal program output, not logged") 67 """ # fmt: skip 68 # Capture the logger 69 if name: 70 # specific logger 71 logger = logging.getLogger(name) 72 else: 73 # root logger 74 logger = logging.getLogger() 75 76 # Create a stream handler 77 import sys 78 79 stream_handler = logging.StreamHandler(sys.stdout) 80 81 # Create a rotating file handler 82 if logfile: 83 from logging.handlers import RotatingFileHandler 84 85 rf_handler = RotatingFileHandler(logfile, maxBytes=25 * 1024, backupCount=5) 86 87 # Set the logs level 88 if verbosity in ["CRITICAL", "FATAL"] or verbosity == -1: 89 level = logging.CRITICAL 90 elif verbosity == "ERROR" or verbosity == 0: 91 level = logging.WARNING 92 elif verbosity == "WARNING" or verbosity == 1: 93 level = logging.WARNING 94 elif verbosity == "INFO" or verbosity == 2: 95 level = logging.INFO 96 elif verbosity == "DEBUG" or verbosity == 3: 97 level = logging.DEBUG 98 else: 99 level = logging.DEBUG 100 logger.setLevel(level) 101 stream_handler.setLevel(level) 102 if logfile: 103 rf_handler.setLevel(level) 104 105 # formatter 106 # "%(asctime)s %(levelname)s %(name)s %(filename)s:%(lineno)d %(message)s", datefmt="%Y-%m-%d %H:%M:%S" 107 formatter = logging.Formatter( 108 "%(asctime)s %(levelname)s %(name)s %(message)s", 109 datefmt="%Y-%m-%d %H:%M:%S", 110 ) 111 stream_handler.setFormatter(formatter) 112 if logfile: 113 rf_handler.setFormatter(formatter) 114 115 # Add the handlers to the logger 116 logger.addHandler(stream_handler) 117 if logfile: 118 logger.addHandler(rf_handler) 119 logger.debug("Logger initialized @level %s", logging.getLevelName(level)) 120 121 return logger 122 123 124def setup_file(name="unknown", filepath=Path().cwd()): 125 """Setups the NAME and FILEPATH variables for modules 126 Tries getting them from __main__.__file__ and __main__.__package__ 127 If it's the __main__ entry point, tries to use the package name 128 Args: 129 main: __main__ from the calling script 130 name: if fails, returns name (default "unknown") 131 here: if fails, returns here Path (default "cwd") 132 """ 133 import __main__ 134 135 if filestr := getattr(__main__, "__file__", None): 136 file = Path(filestr) 137 NAME = file.stem 138 if NAME == "__main__": 139 if package := getattr(__main__, "__package__", None): 140 NAME = package + "_main" 141 else: 142 NAME = name 143 FILEPATH = file.parent 144 else: 145 NAME = name 146 FILEPATH = filepath 147 logger.warning("setup_file(%s, %s) __main__:%s", NAME, FILEPATH, __main__) 148 return NAME, FILEPATH
49def setup_logger(name: str = __name__, verbosity: int = 0, logfile: Path = None): 50 r"""Capture the logger and setup name, verbosity, stream handler & rotating logfile if provided. 51 Args: 52 name (str, optional): Name of the logger. Defaults to \__name __ 53 verbosity (str | int): Verbosity level, implemented, WARNING:1, INFO:2 (default), or DEBUG:3 54 logfile (Path, optional): Create a -rotated- logfile (5 files, 25MB each). 55 Returns: 56 logger (Logger): All code in this pkg uses logger.info("..."), logger.debug, etc. 57 58 ## Developers implementing their own logger 59 * All fire2a modules uses `logger = logging.getLogger(__name__)` 60 61 # Regular Usage Guideline 62 logging.critical("Something went wrong, exception info?", exc_info=True) 63 logging.error("Something went wrong, but we keep going?") 64 logging.warning("Default message level") 65 logging.info("Something planned happened") 66 logging.debug("Details of the planned thing that happened") 67 print("Normal program output, not logged") 68 """ # fmt: skip 69 # Capture the logger 70 if name: 71 # specific logger 72 logger = logging.getLogger(name) 73 else: 74 # root logger 75 logger = logging.getLogger() 76 77 # Create a stream handler 78 import sys 79 80 stream_handler = logging.StreamHandler(sys.stdout) 81 82 # Create a rotating file handler 83 if logfile: 84 from logging.handlers import RotatingFileHandler 85 86 rf_handler = RotatingFileHandler(logfile, maxBytes=25 * 1024, backupCount=5) 87 88 # Set the logs level 89 if verbosity in ["CRITICAL", "FATAL"] or verbosity == -1: 90 level = logging.CRITICAL 91 elif verbosity == "ERROR" or verbosity == 0: 92 level = logging.WARNING 93 elif verbosity == "WARNING" or verbosity == 1: 94 level = logging.WARNING 95 elif verbosity == "INFO" or verbosity == 2: 96 level = logging.INFO 97 elif verbosity == "DEBUG" or verbosity == 3: 98 level = logging.DEBUG 99 else: 100 level = logging.DEBUG 101 logger.setLevel(level) 102 stream_handler.setLevel(level) 103 if logfile: 104 rf_handler.setLevel(level) 105 106 # formatter 107 # "%(asctime)s %(levelname)s %(name)s %(filename)s:%(lineno)d %(message)s", datefmt="%Y-%m-%d %H:%M:%S" 108 formatter = logging.Formatter( 109 "%(asctime)s %(levelname)s %(name)s %(message)s", 110 datefmt="%Y-%m-%d %H:%M:%S", 111 ) 112 stream_handler.setFormatter(formatter) 113 if logfile: 114 rf_handler.setFormatter(formatter) 115 116 # Add the handlers to the logger 117 logger.addHandler(stream_handler) 118 if logfile: 119 logger.addHandler(rf_handler) 120 logger.debug("Logger initialized @level %s", logging.getLevelName(level)) 121 122 return logger
Capture the logger and setup name, verbosity, stream handler & rotating logfile if provided. Args: name (str, optional): Name of the logger. Defaults to __name __ verbosity (str | int): Verbosity level, implemented, WARNING:1, INFO:2 (default), or DEBUG:3 logfile (Path, optional): Create a -rotated- logfile (5 files, 25MB each). Returns: logger (Logger): All code in this pkg uses logger.info("..."), logger.debug, etc.
Developers implementing their own logger
* All fire2a modules uses `logger = logging.getLogger(__name__)`
Regular Usage Guideline
logging.critical("Something went wrong, exception info?", exc_info=True)
logging.error("Something went wrong, but we keep going?")
logging.warning("Default message level")
logging.info("Something planned happened")
logging.debug("Details of the planned thing that happened")
print("Normal program output, not logged")
125def setup_file(name="unknown", filepath=Path().cwd()): 126 """Setups the NAME and FILEPATH variables for modules 127 Tries getting them from __main__.__file__ and __main__.__package__ 128 If it's the __main__ entry point, tries to use the package name 129 Args: 130 main: __main__ from the calling script 131 name: if fails, returns name (default "unknown") 132 here: if fails, returns here Path (default "cwd") 133 """ 134 import __main__ 135 136 if filestr := getattr(__main__, "__file__", None): 137 file = Path(filestr) 138 NAME = file.stem 139 if NAME == "__main__": 140 if package := getattr(__main__, "__package__", None): 141 NAME = package + "_main" 142 else: 143 NAME = name 144 FILEPATH = file.parent 145 else: 146 NAME = name 147 FILEPATH = filepath 148 logger.warning("setup_file(%s, %s) __main__:%s", NAME, FILEPATH, __main__) 149 return NAME, FILEPATH
Setups the NAME and FILEPATH variables for modules Tries getting them from __main__.__file__ and __main__.__package__ If it's the __main__ entry point, tries to use the package name Args: main: __main__ from the calling script name: if fails, returns name (default "unknown") here: if fails, returns here Path (default "cwd")