Repository: bokeh/bokeh

Issue:
VBox/HBox should accept single list as well
Seen in the wild:

```
# `foo` is a dict with Plots as values
VBox(foo.values())
```

Need checks in these two places:

https://github.com/bokeh/bokeh/blob/master/bokeh/models/widgets/layouts.py#L31
https://github.com/bokeh/bokeh/blob/master/bokeh/models/widgets/layouts.py#L48

to check if `len(args)==1` and if `args[0]` is a sequence (list, tuple, etc), then set `kwargs["children"] = args`

Edit: docstrings should also be updated to reflect the different ways to initialize the `children`.



Discussion:
Working on it now.

I made a superclass `BaseBox` that `VBox` and `HBox` inherit from, so that the code for the children property and the `__init__` does not have to be duplicated. Is this ok? Not sure what the effect this has on the client-side or doc generation.

Also, I assume there are plans for other layouts that work in different ways, which is why children and the `__init__` were not defined on the `Layout` class?

I'm not aware of any specific plans, but that seems reasonable. :) Off the cuff, a `Grid` layout would probably be useful. `BaseBox` is fine, it should just be documented like all the other models and it will automatically show up in the Sphinx reference guide. It has no effect on the client side, what matters is the actual type (and view mode type, really) at serialization time. Serialize a `VBox` in python, get a `VBox` in the client. There are often identical hierarchies on both sides, but this is not required (i.e., no requirement for a `BaseBox` on the client side, too)


Resolving patch:
diff --git a/bokeh/models/widgets/layouts.py b/bokeh/models/widgets/layouts.py
--- a/bokeh/models/widgets/layouts.py
+++ b/bokeh/models/widgets/layouts.py
@@ -20,39 +20,43 @@ class Layout(Widget):
     An optional height for the widget (in pixels).
     """)
 
-class HBox(Layout):
-    """ Lay out child widgets in a single horizontal row.
 
+class BaseBox(Layout):
+    """ Abstract base class for HBox and VBox. Do not use directly.
     """
-
+    
     def __init__(self, *args, **kwargs):
         if len(args) > 0 and "children" in kwargs:
             raise ValueError("'children' keyword cannot be used with positional arguments")
-        if len(args) > 0:
+        if (len(args) == 1 and hasattr(args[0], '__iter__') and 
+            not isinstance(args[0], Widget)):
+            # Note: check that not Widget, in case Widget/Layout ever gets __iter__
+            kwargs["children"] = list(args[0])
+        elif len(args) > 0:
             kwargs["children"] = list(args)
-        super(HBox, self).__init__(**kwargs)
+        super(BaseBox, self).__init__(**kwargs)
 
     children = List(Instance(Widget), help="""
     The list of children, which can be other widgets (including layouts)
     and plots.
     """)
 
-class VBox(Layout):
-    """ Lay out child widgets in a single vertical row.
 
+class HBox(BaseBox):
+    """ Lay out child widgets in a single horizontal row.
+    
+    Children can be specified as positional arguments, as a single argument
+    that is a sequence, or using the ``children`` keyword argument.
     """
 
-    def __init__(self, *args, **kwargs):
-        if len(args) > 0 and "children" in kwargs:
-            raise ValueError("'children' keyword cannot be used with positional arguments")
-        if len(args) > 0:
-            kwargs["children"] = list(args)
-        super(VBox, self).__init__(**kwargs)
 
-    children = List(Instance(Widget), help="""
-    The list of children, which can be other widgets (including layouts)
-    and plots.
-    """)
+class VBox(BaseBox):
+    """ Lay out child widgets in a single vertical row.
+    
+    Children can be specified as positional arguments, as a single argument
+    that is a sequence, or using the ``children`` keyword argument.
+    """
+
 
 # parent class only, you need to set the fields you want
 class VBoxForm(VBox):
diff --git a/examples/charts/scatter.py b/examples/charts/scatter.py
--- a/examples/charts/scatter.py
+++ b/examples/charts/scatter.py
@@ -42,4 +42,4 @@
 
 output_file("scatter.html")
 
-show(VBox(scatter1, scatter2, scatter3, scatter4))
+show(VBox([scatter1, scatter2, scatter3, scatter4]))


Test patch: