Repository: bokeh/bokeh

Issue:
Add max_retry_attempts and retry_interval_ms for ImageURLView
I would like to be able to retry loading an image within `image_url` if for some reason there is an error while requesting the image (e.g. HTTP 404).

I'd like to add two properties to Bokeh:

`max_retry_attempts`: int value for number of times to continue to attempt to load image.
`retry_interval_ms`: millisecond value for how often to retry in the event of load error.

then implement logic in `ImageURLView` for `img.onerror`



Discussion:
ref issue: #2786 


Resolving patch:
diff --git a/bokeh/models/glyphs.py b/bokeh/models/glyphs.py
--- a/bokeh/models/glyphs.py
+++ b/bokeh/models/glyphs.py
@@ -9,7 +9,7 @@
 from ..mixins import FillProps, LineProps, TextProps
 from ..model import Model
 from ..properties import (abstract, AngleSpec, Bool, DistanceSpec, Enum, Float,
-                          Include, Instance, NumberSpec, StringSpec)
+                          Include, Instance, Int, NumberSpec, StringSpec)
 from .. import themes
 
 from .mappers import LinearColorMapper
@@ -464,6 +464,16 @@ class ImageURL(Glyph):
     coordinates.
     """)
 
+    retry_attempts = Int(0, help="""
+    Number of attempts to retry loading the images from the specified URL.
+    Default is zero.
+    """)
+
+    retry_timeout = Int(0, help="""
+    Timeout (in ms) between retry attempts to load the image from the
+    specified URL. Default is zero ms.
+    """)
+
 class Line(Glyph):
     """ Render a single line.
 


Test patch:
diff --git a/bokeh/models/tests/test_glyphs.py b/bokeh/models/tests/test_glyphs.py
--- a/bokeh/models/tests/test_glyphs.py
+++ b/bokeh/models/tests/test_glyphs.py
@@ -254,6 +254,8 @@ def test_ImageURL():
     assert glyph.angle == 0
     assert glyph.dilate == False
     assert glyph.anchor == Anchor.top_left
+    assert glyph.retry_attempts == 0
+    assert glyph.retry_timeout == 0
     assert glyph.global_alpha == 1.0
     yield (check_props, glyph, [
         "url",
@@ -267,6 +269,8 @@ def test_ImageURL():
         "angle_units",
         "dilate",
         "anchor",
+        "retry_attempts",
+        "retry_timeout",
         "global_alpha",
     ])
 
diff --git a/bokehjs/test/test_renderer/index.coffee b/bokehjs/test/test_renderer/index.coffee
--- a/bokehjs/test/test_renderer/index.coffee
+++ b/bokehjs/test/test_renderer/index.coffee
@@ -1 +1,2 @@
+require "./test_image_url"
 require "./test_tile"
diff --git a/bokehjs/test/test_renderer/test_image_url.coffee b/bokehjs/test/test_renderer/test_image_url.coffee
new file mode 100644
--- /dev/null
+++ b/bokehjs/test/test_renderer/test_image_url.coffee
@@ -0,0 +1,19 @@
+{expect} = require "chai"
+utils = require "../utils"
+sinon = require 'sinon'
+
+base = utils.require "common/base"
+{Collections} = base
+
+describe "image_url renderer", ->
+  describe "default creation", ->
+    r = Collections('ImageURL').create()
+
+    it "should have global_alpha=1.0", ->
+      expect(r.get('global_alpha')).to.be.equal 1.0
+
+    it "should have retry_attempts=0", ->
+      expect(r.get('retry_attempts')).to.be.equal 0
+
+    it "should have retry_timeout=0", ->
+      expect(r.get('retry_timeout')).to.be.equal 0