Repository: bokeh/bokeh

Issue:
deprecate glyph functions accepting datasource and sequence literals simultanously
Right now, when user passes datasource and passed in data on glyph functions [checks for a passed in source](https://github.com/bokeh/bokeh/blob/master/bokeh/_glyph_functions.py#L9) and [tries to figure out](https://github.com/bokeh/bokeh/blob/master/bokeh/_glyph_functions.py#L40) what the pile of parameters correspond to, given whatever glyph we are and then in that function it actually sets columns on the data source.

We should just disallow it. If you pass in a data source, you only get to refer to constant values, or column names and if you pass data in, then you should not specify datasource.



Discussion:
ping @pzwang and @bokeh/core for opinions..

reference: #2046

For context the problems with allowing `p.rect([1,2,3], [4,5,6], w, h, source=source)` are these:
- This writes new `'x'` and `'y'` columns to `source`. If you had previous values there (from a previous call to `rect`, say), then oops! you just erased them with no warning
- makes it _extremely_ easy to break the "same column size" assumption

Definitely +1 on allowing _either_

```
p.rect([1,2,3], [4,5,6], w, h)
```

_or_

```
p.rect('xfoo', 'ything', w, h, source=source)
```

but not a mixture of both. If agreed, we can make this issue the `task` to do the work. 

[Offline discussion] @pzwang is +1

+1

PR above was never merged but could be used as a starting place for implementing. 


Resolving patch:
diff --git a/bokeh/plotting/helpers.py b/bokeh/plotting/helpers.py
--- a/bokeh/plotting/helpers.py
+++ b/bokeh/plotting/helpers.py
@@ -18,6 +18,7 @@
     WheelPanTool, WheelZoomTool, ColumnDataSource, GlyphRenderer)
 
 from ..core.properties import ColorSpec, Datetime, value
+from ..util.deprecate import BokehDeprecationWarning
 from ..util.string import nice_join
 
 DEFAULT_PALETTE = ["#f22c40", "#5ab738", "#407ee7", "#df5320", "#00ad9c", "#c33ff3"]
@@ -119,8 +120,13 @@ def _process_legend_kwargs(kwargs):
             # Otherwise just accept folks were being intentional
             kwargs['label'] = legend
 
+_GLYPH_SOURCE_MSG = """
+Supplying a user-defined data source AND iterable values to glyph methods is deprecated.
 
-def _process_sequence_literals(glyphclass, kwargs, source):
+See https://github.com/bokeh/bokeh/issues/2056 for more information.
+"""
+
+def _process_sequence_literals(glyphclass, kwargs, source, is_user_source):
     dataspecs = glyphclass.dataspecs_with_props()
     for var, val in kwargs.items():
 
@@ -143,6 +149,9 @@ def _process_sequence_literals(glyphclass, kwargs, source):
         if isinstance(val, np.ndarray) and val.ndim != 1:
             raise RuntimeError("Columns need to be 1D (%s is not)" % var)
 
+        if is_user_source:
+            warnings.warn(_GLYPH_SOURCE_MSG, BokehDeprecationWarning, stacklevel=2)
+
         source.add(val, name=var)
         kwargs[var] = var
 
@@ -412,6 +421,8 @@ def _glyph_function(glyphclass, extra_docs=None):
     def func(self, *args, **kwargs):
 
         _process_legend_kwargs(kwargs)
+        # Need to check if user source is present before _pop_renderer_args
+        is_user_source = kwargs.get('source', None) is not None
         renderer_kws = _pop_renderer_args(kwargs)
         source = renderer_kws['data_source']
 
@@ -421,8 +432,8 @@ def func(self, *args, **kwargs):
 
         # handle the main glyph, need to process literals
         glyph_ca = _pop_colors_and_alpha(glyphclass, kwargs)
-        _process_sequence_literals(glyphclass, kwargs, source)
-        _process_sequence_literals(glyphclass, glyph_ca, source)
+        _process_sequence_literals(glyphclass, kwargs, source, is_user_source)
+        _process_sequence_literals(glyphclass, glyph_ca, source, is_user_source)
 
         # handle the nonselection glyph, we always set one
         nsglyph_ca = _pop_colors_and_alpha(glyphclass, kwargs, prefix='nonselection_', default_alpha=0.1)


Test patch: