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

Dynamically changing the CSS attributes of single outputs in Jupyter notebooks. #15628

Open
ColinConwell opened this issue Jan 11, 2024 · 3 comments

Comments

@ColinConwell
Copy link

While building a CustomLogger, I have for awhile now been struggling to figure out a way to mimic and then modify one simple attribute of sys.stderr outputs: the light red background.

Basically, all I want to do is be able to dynamically specify the background color of a single print statement, without modifying anything else -- and without having to display() custom HTML (which tends to have different effects across different IDEs (JupyterLab, VSCode, JetBrains).

I've tried mime-type-rendering, custom CSS / JS injection / modifying IOThread...

Is there something simple that I am missing or is this as complicated as it seems to be?

My ideal would be have something as simple as print('Some message', file=sys.stderr), but instead of sys.stderr, some other custom message that modifies the background color of the printed line.

Copy link

welcome bot commented Jan 11, 2024

Thank you for opening your first issue in this project! Engagement like this is essential for open source projects! 🤗

If you haven't done so already, check out Jupyter's Code of Conduct. Also, please try to follow the issue template as it helps other other community members to contribute more effectively.
welcome
You can meet the other Jovyans by joining our Discourse forum. There is also an intro thread there where you can stop by and say Hi! 👋

Welcome to the Jupyter community! 🎉

@jupyterlab-probot jupyterlab-probot bot added the status:Needs Triage Applied to new issues that need triage label Jan 11, 2024
@krassowski
Copy link
Member

JupyterLab supports ANSI escape codes for colour selection - did you consider these?

For example:

import sys
print(
    '\033[41m' + 'some red text' + '\033[39m',
    file=sys.stderr
)

Screenshot from 2024-01-13 14-11-29

There are of course many packages which make it much easier to use (e.g. colorama).

@ColinConwell
Copy link
Author

ColinConwell commented Jan 13, 2024

Thanks so much for your response! Yes, this is one option. I have played around with ansi, qlogging, and many other variants.

But it's a bit undesirable in this case, because the background is applied only to the text, rather than to whole rendered text div, which is what I'm after.

Here's some code that does what I want, but basically by invoking Javascript on the last rendered text. This doesn't work across multiple cells, though.

class CustomLogger(logging.Handler):
    def __init__(self, level=logging.NOTSET):
        super().__init__(level)

    def emit(self, record):
        message = self.format(record)
        self.send_to_jupyter(message)

    @staticmethod
    def set_style(verbose=False):
        html_code="""
        <style>
        .custom-log-style {
            background: aliceblue;
        }
        </style>
        """
        display(HTML(html_code))
        if verbose:
            print('added custom log style')

    def send_to_jupyter(self, message):
        # Using standard JavaScript to manipulate the DOM
        js_code = """
        function applyStyle() {
            var selector = ".jp-RenderedText[data-mime-type='application/vnd.jupyter.stdout']"
            //var selector = '.jp-RenderedText'
            var outputs = document.querySelectorAll(selector);
            if (outputs.length > 0) {
                var last_output = outputs[outputs.length - 1];
                last_output.classList.add('custom-log-style');
                }
            }
        applyStyle();
        """
        print('This is the message')
        display(Javascript(js_code))

logger = logging.getLogger("CustomLogger")
CustomLogger.set_style(verbose=False)
logger.setLevel(logging.INFO)
logger.handlers.clear() # reset
logger.addHandler(CustomLogger())

logger.info("This is a custom styled log message.")

It would be nice simply to have a method for setting the css of a single IOStream output, or creating a custom IOStream, and supply that to print's file (as with sys.stderr).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants