fire2a

This is Wildfires/Forest Fire Advanced Analytics (fire2a) algorithms library 🌲🔥🧠📚 api documentation.

Get it from PyPI: pip install fire2a-lib

Important links:

End user documentation : https://fire2a.github.io/docs Use our tools with zero coding!

Source code and development tips : https://github.com/fire2a/fire2a-lib Get help or contribute!

Public contact : e-mail

Public website : www.fire2a.com

Please browse or search using the sidebar to the left!

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

def setup_file(name='unknown', filepath=PosixPath('/__w/fire2a-lib/fire2a-lib')):
121def setup_file(name="unknown", filepath=Path().cwd()):
122    """Setups the NAME and FILEPATH variables for modules
123    Tries getting them from __main__.__file__ and __main__.__package__
124    If it's the __main__ entry point, tries to use the package name
125    Args:
126        main: __main__ from the calling script
127        name: if fails, returns name (default "unknown")
128        here: if fails, returns here Path (default "cwd")
129    """
130    import __main__
131
132    if filestr := getattr(__main__, "__file__", None):
133        file = Path(filestr)
134        NAME = file.stem
135        if NAME == "__main__":
136            if package := getattr(__main__, "__package__", None):
137                NAME = package + "_main"
138            else:
139                NAME = name
140        FILEPATH = file.parent
141    else:
142        NAME = name
143        FILEPATH = filepath
144    logger.warning("setup_file(%s, %s) __main__:%s", NAME, FILEPATH, __main__)
145    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")