possibility to pass parameters and get return value from the Button `on_click` method

Is there a way to pass parameters and get return value from the Button on_click method ?

Thanks,

Vincent

Hi Vincent,

I don’t think that’s possible. What’s your use-case?

Regards,

Eugene

···

On Sunday, February 18, 2018 at 7:50:07 PM UTC+7, Vincent Konaté wrote:

Is there a way to pass parameters and get return value from the Button on_click method ?

https://bokeh.pydata.org/en/latest/docs/reference/models/widgets.buttons.html#bokeh.models.widgets.buttons.Button.on_click

Thanks,

Vincent

Well there is a lot of cases where this is very limiting.

For instance lets consider the following simple chart:

def price():
index=pd.date_range(‘2017-12-11’,‘2017-12-12’,freq=‘10T’,tz=‘UTC’)
data=np.random.rand(len(index))
data[-2:]=[0,1] # create min and max for range assert
price=CDS(dict(datetime=index,close=data,volume=volume,month=months))
return price

def chart():
chart=figure(width=500,height=200,x_axis_type=‘datetime’)
chart.line(‘datetime’,‘close’,source=price())
return chart

``

I can add a callback on range change as such:

def update_x_range(attrname, old, new):
print(old, new)
c.add_layout(BoxAnnotation(bottom=0.5, top=0.6,fill_color=‘green’) # this will not work as c is not define in case of multiple charts

c=chart()
c.x_range.on_change(‘end’, update_x_range)

``

But now if i create 3 of thoses charts a put them in a column

col=column()
for x in range(3):
c=chart()
c.x_range.on_change(‘end’, update_x_range)
col.children.append(c)

``

How can I have the update_x_range method only perform only on the charts that triggered it?

NB: This is only 1 of many cases where it would have been super handy to have more flexibility in the callbacks.

Doing test (i.e. with pytest) is another one.

Best,

Vincent

···

Le dimanche 18 février 2018 12:51:29 UTC, Eugene Pakhomov a écrit :

Hi Vincent,

I don’t think that’s possible. What’s your use-case?

Regards,

Eugene

On Sunday, February 18, 2018 at 7:50:07 PM UTC+7, Vincent Konaté wrote:

Is there a way to pass parameters and get return value from the Button on_click method ?

https://bokeh.pydata.org/en/latest/docs/reference/models/widgets.buttons.html#bokeh.models.widgets.buttons.Button.on_click

Thanks,

Vincent

You have to create three separate callbacks. In your example, you have “c” captured in the callback, so it will be the last assigned to “c” value that’s getting used in the callback.
Instead, write this:

col_children =
for _ in range(3):
c = chart()

def update_x_range(attr, old, new):
    ...  # `c` here will be the correct one

c.x_range.on_change('end', update_x_range)
col_children.append(c)

It’s generally better to create objects with relevant data

rather than to alter already created objects

col = column(col_children)

``

Similar cases where you want to use something similar in different contexts can all be resolved with this approach.

Regards,

Eugene

···

On Monday, February 19, 2018 at 4:43:27 AM UTC+7, Vincent Konaté wrote:

Well there is a lot of cases where this is very limiting.

For instance lets consider the following simple chart:

def price():
index=pd.date_range(‘2017-12-11’,‘2017-12-12’,freq=‘10T’,tz=‘UTC’)
data=np.random.rand(len(index))
data[-2:]=[0,1] # create min and max for range assert
price=CDS(dict(datetime=index,close=data,volume=volume,month=months))
return price

def chart():
chart=figure(width=500,height=200,x_axis_type=‘datetime’)
chart.line(‘datetime’,‘close’,source=price())
return chart

``

I can add a callback on range change as such:

def update_x_range(attrname, old, new):
print(old, new)
c.add_layout(BoxAnnotation(bottom=0.5, top=0.6,fill_color=‘green’) # this will not work as c is not define in case of multiple charts

c=chart()
c.x_range.on_change(‘end’, update_x_range)

``

But now if i create 3 of thoses charts a put them in a column

col=column()
for x in range(3):
c=chart()
c.x_range.on_change(‘end’, update_x_range)
col.children.append(c)

``

How can I have the update_x_range method only perform only on the charts that triggered it?

NB: This is only 1 of many cases where it would have been super handy to have more flexibility in the callbacks.

Doing test (i.e. with pytest) is another one.

Best,

Vincent

Le dimanche 18 février 2018 12:51:29 UTC, Eugene Pakhomov a écrit :

Hi Vincent,

I don’t think that’s possible. What’s your use-case?

Regards,

Eugene

On Sunday, February 18, 2018 at 7:50:07 PM UTC+7, Vincent Konaté wrote:

Is there a way to pass parameters and get return value from the Button on_click method ?

https://bokeh.pydata.org/en/latest/docs/reference/models/widgets.buttons.html#bokeh.models.widgets.buttons.Button.on_click

Thanks,

Vincent

This is not a good answer as it cannot scale up. You are giving a hack as an answer to a question that simplify greatly the real use case.

In my real life example i want to store the callbacks in a separate module as a code has become too large and unmaintainable.

With this kind of answers you only prove that bokeh cannot be used for large projects.

···

On 19 Feb 2018 04:40, “Eugene Pakhomov” [email protected] wrote:

You have to create three separate callbacks. In your example, you have “c” captured in the callback, so it will be the last assigned to “c” value that’s getting used in the callback.
Instead, write this:

col_children =
for _ in range(3):
c = chart()

def update_x_range(attr, old, new):
    ...  # `c` here will be the correct one

c.x_range.on_change('end', update_x_range)
col_children.append(c)

It’s generally better to create objects with relevant data

rather than to alter already created objects

col = column(col_children)

``

Similar cases where you want to use something similar in different contexts can all be resolved with this approach.

Regards,

Eugene

On Monday, February 19, 2018 at 4:43:27 AM UTC+7, Vincent Konaté wrote:

Well there is a lot of cases where this is very limiting.

For instance lets consider the following simple chart:

def price():
index=pd.date_range(‘2017-12-11’,‘2017-12-12’,freq=‘10T’,tz=‘UTC’)
data=np.random.rand(len(index))
data[-2:]=[0,1] # create min and max for range assert
price=CDS(dict(datetime=index,close=data,volume=volume,month=months))
return price

def chart():
chart=figure(width=500,height=200,x_axis_type=‘datetime’)
chart.line(‘datetime’,‘close’,source=price())
return chart

``

I can add a callback on range change as such:

def update_x_range(attrname, old, new):
print(old, new)
c.add_layout(BoxAnnotation(bottom=0.5, top=0.6,fill_color=‘green’) # this will not work as c is not define in case of multiple charts

c=chart()
c.x_range.on_change(‘end’, update_x_range)

``

But now if i create 3 of thoses charts a put them in a column

col=column()
for x in range(3):
c=chart()
c.x_range.on_change(‘end’, update_x_range)
col.children.append(c)

``

How can I have the update_x_range method only perform only on the charts that triggered it?

NB: This is only 1 of many cases where it would have been super handy to have more flexibility in the callbacks.

Doing test (i.e. with pytest) is another one.

Best,

Vincent

Le dimanche 18 février 2018 12:51:29 UTC, Eugene Pakhomov a écrit :

Hi Vincent,

I don’t think that’s possible. What’s your use-case?

Regards,

Eugene

On Sunday, February 18, 2018 at 7:50:07 PM UTC+7, Vincent Konaté wrote:

Is there a way to pass parameters and get return value from the Button on_click method ?

https://bokeh.pydata.org/en/latest/docs/reference/models/widgets.buttons.html#bokeh.models.widgets.buttons.Button.on_click

Thanks,

Vincent

You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/PzpppZh-UvQ/unsubscribe.

To unsubscribe from this group and all its topics, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/51cc5687-8548-414a-9d9f-cf9070df417d%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

You’re incorrect, it’s very easy to organize in the way you want:

Module A

def create_x_range_cb(fig):
def cb(attr, old, new):
print(‘Changed x_range.{} of “{}” from {} to {}’.format(attr, fig.name, old, new))

return cb

Module B

from A import create_x_range_cb

fig = figure()

fig.x_range.on_change(‘start’, create_x_range_cb(fig))

``

  • Eugene
···

On Monday, February 19, 2018 at 3:12:10 PM UTC+7, Vincent Konaté wrote:

This is not a good answer as it cannot scale up. You are giving a hack as an answer to a question that simplify greatly the real use case.

In my real life example i want to store the callbacks in a separate module as a code has become too large and unmaintainable.

With this kind of answers you only prove that bokeh cannot be used for large projects.

On 19 Feb 2018 04:40, “Eugene Pakhomov” [email protected] wrote:

You have to create three separate callbacks. In your example, you have “c” captured in the callback, so it will be the last assigned to “c” value that’s getting used in the callback.
Instead, write this:

col_children =
for _ in range(3):
c = chart()

def update_x_range(attr, old, new):
    ...  # `c` here will be the correct one

c.x_range.on_change('end', update_x_range)
col_children.append(c)

It’s generally better to create objects with relevant data

rather than to alter already created objects

col = column(col_children)

``

Similar cases where you want to use something similar in different contexts can all be resolved with this approach.

Regards,

Eugene

On Monday, February 19, 2018 at 4:43:27 AM UTC+7, Vincent Konaté wrote:

Well there is a lot of cases where this is very limiting.

For instance lets consider the following simple chart:

def price():
index=pd.date_range(‘2017-12-11’,‘2017-12-12’,freq=‘10T’,tz=‘UTC’)
data=np.random.rand(len(index))
data[-2:]=[0,1] # create min and max for range assert
price=CDS(dict(datetime=index,close=data,volume=volume,month=months))
return price

def chart():
chart=figure(width=500,height=200,x_axis_type=‘datetime’)
chart.line(‘datetime’,‘close’,source=price())
return chart

``

I can add a callback on range change as such:

def update_x_range(attrname, old, new):
print(old, new)
c.add_layout(BoxAnnotation(bottom=0.5, top=0.6,fill_color=‘green’) # this will not work as c is not define in case of multiple charts

c=chart()
c.x_range.on_change(‘end’, update_x_range)

``

But now if i create 3 of thoses charts a put them in a column

col=column()
for x in range(3):
c=chart()
c.x_range.on_change(‘end’, update_x_range)
col.children.append(c)

``

How can I have the update_x_range method only perform only on the charts that triggered it?

NB: This is only 1 of many cases where it would have been super handy to have more flexibility in the callbacks.

Doing test (i.e. with pytest) is another one.

Best,

Vincent

Le dimanche 18 février 2018 12:51:29 UTC, Eugene Pakhomov a écrit :

Hi Vincent,

I don’t think that’s possible. What’s your use-case?

Regards,

Eugene

On Sunday, February 18, 2018 at 7:50:07 PM UTC+7, Vincent Konaté wrote:

Is there a way to pass parameters and get return value from the Button on_click method ?

https://bokeh.pydata.org/en/latest/docs/reference/models/widgets.buttons.html#bokeh.models.widgets.buttons.Button.on_click

Thanks,

Vincent

You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/PzpppZh-UvQ/unsubscribe.

To unsubscribe from this group and all its topics, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/51cc5687-8548-414a-9d9f-cf9070df417d%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

You can also use functools.partial to bake in any extra parameters you like so that callbacks can be reused. Or similay use methods as callbacks so that lexical self is available.

As for return values I’m not aware of any other event callback system that has that. The library, not the developer, calls callbacks on your behalf, where would return values go? Can you point to existing examples in other systems for comparison? Of course if you really need state to escape a callback there’s any number of ways to do that (call a method on some object, write to a database, etc)

Or do you mean you want a literal RPC mechanism? If so there’s an open issue to add a basic one. If you’d like to help work on it we would be glad to get you started.

Thanks,

Bryan

···

On Feb 19, 2018, at 00:44, Eugene Pakhomov [email protected] wrote:

You’re incorrect, it’s very easy to organize in the way you want:

Module A

def create_x_range_cb(fig):
def cb(attr, old, new):
print(‘Changed x_range.{} of “{}” from {} to {}’.format(attr, fig.name, old, new))

return cb

Module B

from A import create_x_range_cb

fig = figure()

fig.x_range.on_change(‘start’, create_x_range_cb(fig))

``

  • Eugene

On Monday, February 19, 2018 at 3:12:10 PM UTC+7, Vincent Konaté wrote:

This is not a good answer as it cannot scale up. You are giving a hack as an answer to a question that simplify greatly the real use case.

In my real life example i want to store the callbacks in a separate module as a code has become too large and unmaintainable.

With this kind of answers you only prove that bokeh cannot be used for large projects.

On 19 Feb 2018 04:40, “Eugene Pakhomov” [email protected] wrote:

You have to create three separate callbacks. In your example, you have “c” captured in the callback, so it will be the last assigned to “c” value that’s getting used in the callback.
Instead, write this:

col_children =
for _ in range(3):
c = chart()

def update_x_range(attr, old, new):
    ...  # `c` here will be the correct one

c.x_range.on_change('end', update_x_range)
col_children.append(c)

It’s generally better to create objects with relevant data

rather than to alter already created objects

col = column(col_children)

``

Similar cases where you want to use something similar in different contexts can all be resolved with this approach.

Regards,

Eugene

On Monday, February 19, 2018 at 4:43:27 AM UTC+7, Vincent Konaté wrote:

Well there is a lot of cases where this is very limiting.

For instance lets consider the following simple chart:

def price():
index=pd.date_range(‘2017-12-11’,‘2017-12-12’,freq=‘10T’,tz=‘UTC’)
data=np.random.rand(len(index))
data[-2:]=[0,1] # create min and max for range assert
price=CDS(dict(datetime=index,close=data,volume=volume,month=months))
return price

def chart():
chart=figure(width=500,height=200,x_axis_type=‘datetime’)
chart.line(‘datetime’,‘close’,source=price())
return chart

``

I can add a callback on range change as such:

def update_x_range(attrname, old, new):
print(old, new)
c.add_layout(BoxAnnotation(bottom=0.5, top=0.6,fill_color=‘green’) # this will not work as c is not define in case of multiple charts

c=chart()
c.x_range.on_change(‘end’, update_x_range)

``

But now if i create 3 of thoses charts a put them in a column

col=column()
for x in range(3):
c=chart()
c.x_range.on_change(‘end’, update_x_range)
col.children.append(c)

``

How can I have the update_x_range method only perform only on the charts that triggered it?

NB: This is only 1 of many cases where it would have been super handy to have more flexibility in the callbacks.

Doing test (i.e. with pytest) is another one.

Best,

Vincent

Le dimanche 18 février 2018 12:51:29 UTC, Eugene Pakhomov a écrit :

Hi Vincent,

I don’t think that’s possible. What’s your use-case?

Regards,

Eugene

On Sunday, February 18, 2018 at 7:50:07 PM UTC+7, Vincent Konaté wrote:

Is there a way to pass parameters and get return value from the Button on_click method ?

https://bokeh.pydata.org/en/latest/docs/reference/models/widgets.buttons.html#bokeh.models.widgets.buttons.Button.on_click

Thanks,

Vincent

You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/PzpppZh-UvQ/unsubscribe.

To unsubscribe from this group and all its topics, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/51cc5687-8548-414a-9d9f-cf9070df417d%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/0f29db78-7dfd-4b8c-b1c1-2dc5e7578c1e%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Thanks Bryan for your reply.

Regarding functools.partial: will have to try that.

Regarding return: thanks for the hints you are proposing.

I think the simplest for me will be to switch from functional programming to OOP and simply save the results on the instance.

Sorry Eugene if i have been a bit rude.

Best,

Vincent

···

Le lundi 19 février 2018 14:30:43 UTC, Bryan Van de ven a écrit :

You can also use functools.partial to bake in any extra parameters you like so that callbacks can be reused. Or similay use methods as callbacks so that lexical self is available.

As for return values I’m not aware of any other event callback system that has that. The library, not the developer, calls callbacks on your behalf, where would return values go? Can you point to existing examples in other systems for comparison? Of course if you really need state to escape a callback there’s any number of ways to do that (call a method on some object, write to a database, etc)

Or do you mean you want a literal RPC mechanism? If so there’s an open issue to add a basic one. If you’d like to help work on it we would be glad to get you started.

Thanks,

Bryan

On Feb 19, 2018, at 00:44, Eugene Pakhomov [email protected] wrote:

You’re incorrect, it’s very easy to organize in the way you want:

Module A

def create_x_range_cb(fig):
def cb(attr, old, new):
print(‘Changed x_range.{} of “{}” from {} to {}’.format(attr, fig.name, old, new))

return cb

Module B

from A import create_x_range_cb

fig = figure()

fig.x_range.on_change(‘start’, create_x_range_cb(fig))

``

  • Eugene

On Monday, February 19, 2018 at 3:12:10 PM UTC+7, Vincent Konaté wrote:

This is not a good answer as it cannot scale up. You are giving a hack as an answer to a question that simplify greatly the real use case.

In my real life example i want to store the callbacks in a separate module as a code has become too large and unmaintainable.

With this kind of answers you only prove that bokeh cannot be used for large projects.

On 19 Feb 2018 04:40, “Eugene Pakhomov” [email protected] wrote:

You have to create three separate callbacks. In your example, you have “c” captured in the callback, so it will be the last assigned to “c” value that’s getting used in the callback.
Instead, write this:

col_children =
for _ in range(3):
c = chart()

def update_x_range(attr, old, new):
    ...  # `c` here will be the correct one

c.x_range.on_change('end', update_x_range)
col_children.append(c)

It’s generally better to create objects with relevant data

rather than to alter already created objects

col = column(col_children)

``

Similar cases where you want to use something similar in different contexts can all be resolved with this approach.

Regards,

Eugene

On Monday, February 19, 2018 at 4:43:27 AM UTC+7, Vincent Konaté wrote:

Well there is a lot of cases where this is very limiting.

For instance lets consider the following simple chart:

def price():
index=pd.date_range(‘2017-12-11’,‘2017-12-12’,freq=‘10T’,tz=‘UTC’)
data=np.random.rand(len(index))
data[-2:]=[0,1] # create min and max for range assert
price=CDS(dict(datetime=index,close=data,volume=volume,month=months))
return price

def chart():
chart=figure(width=500,height=200,x_axis_type=‘datetime’)
chart.line(‘datetime’,‘close’,source=price())
return chart

``

I can add a callback on range change as such:

def update_x_range(attrname, old, new):
print(old, new)
c.add_layout(BoxAnnotation(bottom=0.5, top=0.6,fill_color=‘green’) # this will not work as c is not define in case of multiple charts

c=chart()
c.x_range.on_change(‘end’, update_x_range)

``

But now if i create 3 of thoses charts a put them in a column

col=column()
for x in range(3):
c=chart()
c.x_range.on_change(‘end’, update_x_range)
col.children.append(c)

``

How can I have the update_x_range method only perform only on the charts that triggered it?

NB: This is only 1 of many cases where it would have been super handy to have more flexibility in the callbacks.

Doing test (i.e. with pytest) is another one.

Best,

Vincent

Le dimanche 18 février 2018 12:51:29 UTC, Eugene Pakhomov a écrit :

Hi Vincent,

I don’t think that’s possible. What’s your use-case?

Regards,

Eugene

On Sunday, February 18, 2018 at 7:50:07 PM UTC+7, Vincent Konaté wrote:

Is there a way to pass parameters and get return value from the Button on_click method ?

https://bokeh.pydata.org/en/latest/docs/reference/models/widgets.buttons.html#bokeh.models.widgets.buttons.Button.on_click

Thanks,

Vincent

You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/PzpppZh-UvQ/unsubscribe.

To unsubscribe from this group and all its topics, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/51cc5687-8548-414a-9d9f-cf9070df417d%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/0f29db78-7dfd-4b8c-b1c1-2dc5e7578c1e%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.