Repository: bokeh/bokeh

Issue:
Bokeh Spacer sets height to one pixel with scale_width set
#### ALL software version info (bokeh, python, OS, browser, any other relevant packages)
bokeh: 0.12.15
python: 3.6.4
OS: Mac OS 10.12.6
browser: Google Chrome  65.0.3325.181 (Official Build) (64-bit)

#### Description of expected behavior and the observed behavior
I would expect to see a moderate amount of vertical separation between widgets, keeping the width/height ratio constant. However when I inspect the location the element should be, I see that it has a height of 1 pixel, regardless of the aspect ratio. I did not have this issue when putting a Spacer in a row. Putting the plot in the column too and skipping the row does not fix the problem. 

#### Complete, minimal, self-contained example code that reproduces the issue
I modified the `sliders.py` example code to put the widgets in two separate boxes, then grouped them and a spacer in a column. 

```
import numpy as np

from bokeh.io import curdoc
from bokeh.layouts import row, column, widgetbox, Spacer
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Slider, TextInput
from bokeh.plotting import figure

# Set up data
N = 200
x = np.linspace(0, 4*np.pi, N)
y = np.sin(x)
source = ColumnDataSource(data=dict(x=x, y=y))


# Set up plot
plot = figure(plot_height=400, plot_width=400, title="my sine wave",
              tools="crosshair,pan,reset,save,wheel_zoom",
              x_range=[0, 4*np.pi], y_range=[-2.5, 2.5])

plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)


# Set up widgets
text = TextInput(title="title", value='my sine wave')
offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1)
amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0, step=0.1)
phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi)
freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1, step=0.1)


# Set up callbacks
def update_title(attrname, old, new):
    plot.title.text = text.value

text.on_change('value', update_title)

def update_data(attrname, old, new):

    # Get the current slider values
    a = amplitude.value
    b = offset.value
    w = phase.value
    k = freq.value

    # Generate the new curve
    x = np.linspace(0, 4*np.pi, N)
    y = a*np.sin(k*x + w) + b

    source.data = dict(x=x, y=y)

for w in [offset, amplitude, phase, freq]:
    w.on_change('value', update_data)


# Set up layouts and add to document
##### BEGIN RELEVANT SECTION #####
input1 = widgetbox(text, offset)
input2 = widgetbox(amplitude, phase, freq)
inputs = column(input1, 
              Spacer(width=400, height=400, sizing_mode='scale_width'),
              input2, sizing_mode='scale_width')
##### END RELEVANT SECTION #####

curdoc().add_root(row(inputs, plot, sizing_mode='scale_width'))
curdoc().title = "Sliders"
```

#### Screenshots or screencasts of the bug in action
<img width="1341" alt="screen shot 2018-04-17 at 4 29 32 pm" src="https://user-images.githubusercontent.com/13019270/38904007-9d0f4fc6-425c-11e8-9092-408cf54b9d25.png">


Discussion:
Looks like using a `bokeh.models.widgets.Div` with no text acts like a `Spacer` and doesn't have this issue. Guess I'll just use that as a replacement. Weird `Spacer` doesn't work though. 
this also was happening with 0.12.14 but I'm doing a lot of funky custom things with my own JS so I assumed it was me. Good to see if happens elsewhere and that the Div trick stops it (I implemented a watcher to check the height of the spacer element to reset it whenever it changed to be 1px haha)
> Weird Spacer doesn't work though.

Not really, OSS projects are chronically under-resourced. Lesser used features are especially prone to bit-rot and regressions, and e.g. I don't think I've ever even personally tried to use `Spacer` once.  In any case since there is a workaround documented here, I have triaged as "short term" (which will be post 1.0)
This behavior is by design. `Spacer` has special meaning in layout, especially in grids and tree-like layouts, where it's used to fill space occupied by "missing" layout items (e.g. if a child is `None` in a grid). There is a lot of room for improvement here, though in the long term, we should implement proper whitespace management in layout (say #4400, though that one isn't very specific).
Using `Div` may serve as a temporary workaround, however, this solution may not work as expected in newer versions of bokeh. Currently this works, because empty `Div` has intrinsic padding, which seems to be a bug on its own.
This appears to be fixed by #8085:

<img width="1293" alt="screen shot 2019-01-30 at 21 04 55" src="https://user-images.githubusercontent.com/1078448/52031723-bfbbd180-24d2-11e9-89f7-02358afc7beb.png">

however @mattpap it appears `Spacer` was removed from `bokeh.layouts`, we should restore this transitive import from `bokeh.models.layouts`

Resolving patch:
diff --git a/bokeh/layouts.py b/bokeh/layouts.py
--- a/bokeh/layouts.py
+++ b/bokeh/layouts.py
@@ -28,7 +28,7 @@
 from .core.enums import Location
 from .models.tools import ProxyToolbar, ToolbarBox
 from .models.plots import Plot
-from .models.layouts import LayoutDOM, Row, Column, GridBox, WidgetBox
+from .models.layouts import LayoutDOM, Row, Column, GridBox, Spacer, WidgetBox
 
 #-----------------------------------------------------------------------------
 # Globals and constants
@@ -40,6 +40,7 @@
     'GridSpec',
     'layout',
     'row',
+    'Spacer',
     'widgetbox',
 )
 


Test patch: