Skip to content

use cleo in combination with logging #49

Open

Description

@flokli

Hey,

do you have any plans on how to use cleo's self.line and verbosity levels in combination with logger, so log entries might get written (and colored) by a custom cleo handler?

Activity

  1. flokli commented on Jan 10, 2017

    @flokli
    Author

    I had something like click-log in mind.

  2. kam1sh commented on Sep 30, 2019

    @kam1sh

    It's easy to write logging.Handler: just take clikit's IO and check verbosity before calling write_line:

    from clikit.api.io import flags as verbosity
    
    _levels = {
        logging.CRITICAL: verbosity.NORMAL,
        logging.ERROR: verbosity.NORMAL,
        logging.WARNING: verbosity.NORMAL,
        logging.INFO: verbosity.VERY_VERBOSE,
        logging.DEBUG: verbosity.DEBUG,
    }
    
    
    class ClikitHandler(logging.Handler):
        """Logging handler that redirects all messages to clikit io object."""
    
        def __init__(self, io, level=logging.NOTSET):
            super().__init__(level=level)
            self.io = io
    
        def emit(self, record: logging.LogRecord):
            level = _levels[record.levelno]
            if record.levelno >= logging.WARNING:
                text = record.getMessage()
                self.io.error_line(text, flags=level)
            elif self.io.verbosity >= level:
                text = record.getMessage()
                self.io.write_line(text)
    
        @classmethod
        def setup_for(cls, name, io):
            log = logging.getLogger(name)
            log.setLevel(logging.DEBUG)
            log.handlers = [cls(io)]
            log.debug("Logger initialized.")

    Much harder, IMO, is to get that IO between IO initialization and running command. I solved this by calling ClikitHandler.setup_for right after ApplicationConfig.create_io():

    from cleo.config.application_config import ApplicationConfig
    from hypai.logging import ClikitHandler
    
    class App(cleo.Application):
        def __init__(self, config=None):
            super().__init__(config=config or AppConfig())
            self.add(BuildDebian())
    
    
    class AppConfig(ApplicationConfig):
        def __init__(self):
            super().__init__("hypai", version=__version__)
    
    
    class LoggingAppConfig(AppConfig):
        def create_io(self, *args, **kwargs):
            io = super().create_io(*args, **kwargs)
            ClikitHandler.setup_for("hypai", io)
            return io
    
    
    def main():
        config = LoggingAppConfig()
        app = App(config=config)
        app.run()

    P.S.: this is not necroposting, I just want to help others struggling with lack of documentation about CliKit's IO and Cleo-Clikit integration.

  3. esciara commented on Oct 5, 2019

    @esciara

    Actually it is exactly what I was looking for. Thanks @kam1sh !

  4. added this to the Future milestone on Jul 7, 2023
  5. modified the milestones: Future, 3.0 on Nov 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureFeature requests/implementations

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions