Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use cleo in combination with logging #49

Open
flokli opened this issue Dec 21, 2016 · 3 comments · May be fixed by #440
Open

use cleo in combination with logging #49

flokli opened this issue Dec 21, 2016 · 3 comments · May be fixed by #440
Milestone

Comments

@flokli
Copy link

flokli commented Dec 21, 2016

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?

@flokli
Copy link
Author

flokli commented Jan 10, 2017

I had something like click-log in mind.

@kam1sh
Copy link

kam1sh commented Sep 30, 2019

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.

@esciara
Copy link

esciara commented Oct 5, 2019

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

@Secrus Secrus added this to the Future milestone Jul 7, 2023
@Secrus Secrus modified the milestones: Future, 3.0 Nov 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants