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

Theme doesn't apply when using components #4952

Closed
birdsarah opened this Issue Aug 12, 2016 · 5 comments

Comments

Projects
None yet
4 participants
@birdsarah
Member

birdsarah commented Aug 12, 2016

Can't get themes to apply when using bokeh.embed.components.

Have tried manually using theme.apply_to_model(model), but it doesn't seem to work.

@birdsarah

This comment has been minimized.

Show comment
Hide comment
@birdsarah

birdsarah Aug 12, 2016

Member

ping @bryevdv - any thoughts

Member

birdsarah commented Aug 12, 2016

ping @bryevdv - any thoughts

@birdsarah birdsarah added the type: bug label Aug 12, 2016

@bryevdv

This comment has been minimized.

Show comment
Hide comment
@bryevdv

bryevdv Aug 15, 2016

Member

Not offhand, I have a vague recollection of seeing this now, so thanks for capturing the issue.

Member

bryevdv commented Aug 15, 2016

Not offhand, I have a vague recollection of seeing this now, so thanks for capturing the issue.

@postelrich

This comment has been minimized.

Show comment
Hide comment
@postelrich

postelrich Oct 31, 2016

Ran into the same or similar issue trying to set the theme of the curdoc when outputting to a notebook.

from bokeh.io import cur_doc, show, output_notebook
from bokeh.themes import Theme

curdoc().theme = Theme(json={'attrs': {'Title': {'text_color': 'pink'}}})

postelrich commented Oct 31, 2016

Ran into the same or similar issue trying to set the theme of the curdoc when outputting to a notebook.

from bokeh.io import cur_doc, show, output_notebook
from bokeh.themes import Theme

curdoc().theme = Theme(json={'attrs': {'Title': {'text_color': 'pink'}}})
@djpugh

This comment has been minimized.

Show comment
Hide comment
@djpugh

djpugh Nov 16, 2016

Contributor

I've hit this too, and it looks like it is because components uses a

with _ModelInDocument:

Which adds the model to a document, which combined with _attach_document in model.py applies the document theme and then the default theme if it is removed. It seems to work if you add the model to a document before calling components:

p = figure()
curdoc().theme = Theme(json={'attrs': {'Title': {'text_color': 'pink'}}})
cudoc().add_root(p)
script, div = components(p)

@bryevdv - I'm happy to look at a fix, I guess the obvious one would be to do something to preserve the theme in the with _ModelInDocument: call even if the model is not in a document

Contributor

djpugh commented Nov 16, 2016

I've hit this too, and it looks like it is because components uses a

with _ModelInDocument:

Which adds the model to a document, which combined with _attach_document in model.py applies the document theme and then the default theme if it is removed. It seems to work if you add the model to a document before calling components:

p = figure()
curdoc().theme = Theme(json={'attrs': {'Title': {'text_color': 'pink'}}})
cudoc().add_root(p)
script, div = components(p)

@bryevdv - I'm happy to look at a fix, I guess the obvious one would be to do something to preserve the theme in the with _ModelInDocument: call even if the model is not in a document

@djpugh

This comment has been minimized.

Show comment
Hide comment
@djpugh

djpugh Nov 17, 2016

Contributor

Something like:

class _ModelInDocument(object):
    # 'models' can be a single Model, a single Document, or a list of either
    def __init__(self, models):
        from .document import Document
        self._to_remove_after = []
        self._theme = []
        if not isinstance(models, list):
            models = [models]

        self._doc = _find_some_document(models)
        if self._doc is None:
            # oh well - just make up a doc
            self._doc = Document()

        for model in models:
            if isinstance(model, Model):
                if model.document is None:
                    # Gets the model theme (or None if no theme)
                    self._theme.append(model.themed_values())
                    self._to_remove_after.append(model)

    def __exit__(self, type, value, traceback):
        for i, model in enumerate(self._to_remove_after):
            model.document.remove_root(model)
            if self._theme[i] is not None:
                # Applies the model theme after removing the document
                model.apply_theme(self._theme[i])

    def __enter__(self):
        for i, model in enumerate(self._to_remove_after):
            # This should preserve model theming here
            self._doc.add_root(model)
            if self._theme[i] is not None:
                # Applies the model theme after adding the document
                model.apply_theme(self._theme[i])

But I'm not sure if this would have repercussions elsewhere - otherwise this could be done around the with loop in embed.py.

Contributor

djpugh commented Nov 17, 2016

Something like:

class _ModelInDocument(object):
    # 'models' can be a single Model, a single Document, or a list of either
    def __init__(self, models):
        from .document import Document
        self._to_remove_after = []
        self._theme = []
        if not isinstance(models, list):
            models = [models]

        self._doc = _find_some_document(models)
        if self._doc is None:
            # oh well - just make up a doc
            self._doc = Document()

        for model in models:
            if isinstance(model, Model):
                if model.document is None:
                    # Gets the model theme (or None if no theme)
                    self._theme.append(model.themed_values())
                    self._to_remove_after.append(model)

    def __exit__(self, type, value, traceback):
        for i, model in enumerate(self._to_remove_after):
            model.document.remove_root(model)
            if self._theme[i] is not None:
                # Applies the model theme after removing the document
                model.apply_theme(self._theme[i])

    def __enter__(self):
        for i, model in enumerate(self._to_remove_after):
            # This should preserve model theming here
            self._doc.add_root(model)
            if self._theme[i] is not None:
                # Applies the model theme after adding the document
                model.apply_theme(self._theme[i])

But I'm not sure if this would have repercussions elsewhere - otherwise this could be done around the with loop in embed.py.

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