Repository: bokeh/bokeh

Issue:
document get_screenshot_as_png better
Currently the export_png function in export.py is like the following: 

```
    image = get_screenshot_as_png(obj, height=height, width=width, driver=webdriver)

    if filename is None:
        filename = default_filename("png")

    image.save(filename)

    return abspath(filename)
```
It returns the abspath of the file saved, but is it possible to update it to also return/expose the image? This way it will be easy to save the PIL.Image.Image file to an object in memory, and return file data back in a format that an AWS clients put_object function will accept as the Body parameter:
```
    png_img = export_png(bokeh_fig, filename="xxx")
    in_mem_file = io.BytesIO()
    png_img.save(in_mem_file, format="png")
    _s3.Bucket(bucket_name).put_object(Key="yyy", Body=in_mem_file.getvalue())
```


Discussion:
@wqp89324 For now you can just use `get_screenshot_as_png` directly? It's marked as `dev` API but that still means it will be a public, stable API. It could certainly use some better documentation support. 

I guess the two options are:

* document `get_screenshot_as_png` better, and promote it as the expected way to get images as data
* add a mode for `export_png` to do that

In general I'm usually -1 on having a function return different types (i.e. a file path vs image data) with different inputs, so my inclination is to prefer the first option.  
@bryevdv 
I would agree the first option is fine, but currently in bokeh/bokeh/io/__init__.py, I did not see any import on "get_screenshot_as_png".
How can I import this function into my code?

Thank you so much!
Since it's considered dev/advanced it i in the sub module `bokeh.io.export` we could also consider making it "general" and moving it into `bokeh.io` I don't have a super strong opinion about that I guess I'd be -0, especially if the `export_png` docs link to it

@bryevdv 
I guess I'm asking a stupid question but here it is. When I do:
```
from bokeh.io.export import get_screenshot_as_png
```
I get the error: "ImportError: No module named 'bokeh.io.export'; 'bokeh.io' is not a package"

Could you please help?

Thank you so much!
This was all recently refactored as part of a larger cleanup effort. None of the common public APIs changed but the dev APIs are being shuffled as appropriate. You will need install `0.12.10` or newer for this function at that location, which will be  permanent stable location going forward 
Triaging this issue to document `get_screenshot_as_png` more visibly. 
@bryevdv Could you elaborate on what exactly would you like to see added to the current documentation?
@Roald87 sorry I did not see this until now. I think the following woud be good:

* make sure the function docstring is thorough and complete

* add a section to the sphinx user guide about using this function to get back image objects directly with a few lines of example code. 
@bryevdv I've had a look at it, but I think it is rather complicated. At least I'm not quite sure what a `LayoutDOM` object is and how to use it. 

Resolving patch:
diff --git a/bokeh/io/export.py b/bokeh/io/export.py
--- a/bokeh/io/export.py
+++ b/bokeh/io/export.py
@@ -59,8 +59,8 @@
 def export_png(obj, filename=None, height=None, width=None, webdriver=None):
     ''' Export the ``LayoutDOM`` object or document as a PNG.
 
-    If the filename is not given, it is derived from the script name
-    (e.g. ``/foo/myplot.py`` will create ``/foo/myplot.png``)
+    If the filename is not given, it is derived from the script name (e.g.
+    ``/foo/myplot.py`` will create ``/foo/myplot.png``)
 
     Args:
         obj (LayoutDOM or Document) : a Layout (Row/Column), Plot or Widget
@@ -81,6 +81,10 @@ def export_png(obj, filename=None, height=None, width=None, webdriver=None):
     Returns:
         filename (str) : the filename where the static file is saved.
 
+    If you would like to access an Image object directly, rather than save a
+    file to disk, use the lower-level :func:`~bokeh.io.export.get_screenshot_as_png`
+    function.
+
     .. warning::
         Responsive sizing_modes may generate layouts with unexpected size and
         aspect ratios. It is recommended to use the default ``fixed`` sizing mode.
diff --git a/bokeh/models/map_plots.py b/bokeh/models/map_plots.py
--- a/bokeh/models/map_plots.py
+++ b/bokeh/models/map_plots.py
@@ -131,7 +131,14 @@ class GMapPlot(MapPlot):
     e.g. ``(37.123, -122.404)``. It will be automatically converted into the
     web mercator projection to display properly over google maps tiles.
 
-    Please also note that only ``Range1d`` ranges are supported by ``GMapPlot``.
+    Note that Google Maps exert explicit control over aspect ratios at all
+    times, which imposes some limitations on ``GMapPlot``:
+
+    * Only ``Range1d`` ranges are supported. Attempting to use other range
+      types will result in an error.
+
+    * Usage of ``BoxZoomTool`` is incompatible with ``GMapPlot``. Adding a
+      ``BoxZoomTool`` will have no effect.
 
     .. _Google Map: https://www.google.com/maps/
 
diff --git a/bokeh/models/tools.py b/bokeh/models/tools.py
--- a/bokeh/models/tools.py
+++ b/bokeh/models/tools.py
@@ -223,7 +223,10 @@ class Toolbar(ToolbarBase):
     """)
 
 class ProxyToolbar(ToolbarBase):
-    ''' A toolbar that allow to merge and proxy tools of toolbars in multiple plots. '''
+    ''' A toolbar that allow to merge and proxy tools of toolbars in multiple
+    plots.
+
+    '''
 
 class ToolbarBox(LayoutDOM):
     ''' A layoutable toolbar that can accept the tools of multiple plots, and
@@ -240,14 +243,12 @@ class ToolbarBox(LayoutDOM):
 class PanTool(Drag):
     ''' *toolbar icon*: |pan_icon|
 
-    The pan tool allows the user to pan a Plot by left-dragging
-    a mouse, or on touch devices by dragging a finger or stylus, across
-    the plot region.
+    The pan tool allows the user to pan a Plot by left-dragging a mouse, or on
+    touch devices by dragging a finger or stylus, across the plot region.
 
-    The pan tool also activates the border regions of a Plot for "single
-    axis" panning. For instance, dragging in the vertical border or axis
-    will effect a pan in the vertical direction only, with the horizontal
-    dimension kept fixed.
+    The pan tool also activates the border regions of a Plot for "single axis"
+    panning. For instance, dragging in the vertical border or axis will effect
+    a pan in the vertical direction only, with horizontal dimension kept fixed.
 
     .. |pan_icon| image:: /_images/icons/Pan.png
         :height: 18pt
@@ -340,8 +341,8 @@ class WheelPanTool(Scroll):
     '''
 
     dimension = Enum(Dimension, default="width", help="""
-    Which dimension the wheel pan tool is constrained to act in. By
-    default the wheel pan tool will pan the plot along the x-axis.
+    Which dimension the wheel pan tool is constrained to act in. By default the
+    wheel pan tool will pan the plot along the x-axis.
     """)
 
 class WheelZoomTool(Scroll):
@@ -361,21 +362,21 @@ class WheelZoomTool(Scroll):
     '''
 
     dimensions = Enum(Dimensions, default="both", help="""
-    Which dimensions the wheel zoom tool is constrained to act in. By
-    default the wheel zoom tool will zoom in any dimension, but can be
-    configured to only zoom horizontally across the width of the plot, or
-    vertically across the height of the plot.
+    Which dimensions the wheel zoom tool is constrained to act in. By default
+    the wheel zoom tool will zoom in any dimension, but can be configured to
+    only zoom horizontally across the width of the plot, or vertically across
+    the height of the plot.
     """)
 
     maintain_focus = Bool(default=True, help="""
-    Whether or not zooming tool maintains its focus position. Setting it
-    to False results in a more "gliding" behavior, allowing one to
-    zoom out more smoothly, at the cost of losing the focus position.
+    Whether or not zooming tool maintains its focus position. Setting to False
+    results in a more "gliding" behavior, allowing one to zoom out more
+    smoothly, at the cost of losing the focus position.
     """)
 
     zoom_on_axis = Bool(default=True, help="""
-    Whether scrolling on an axis (outside the central plot area) should
-    zoom that dimension.
+    Whether scrolling on an axis (outside the central plot area) should zoom
+    that dimension.
     """)
 
     speed = Float(default=1/600, help="""
@@ -431,12 +432,9 @@ class SaveTool(Action):
 class ResetTool(Action):
     ''' *toolbar icon*: |reset_icon|
 
-    The reset tool is an action. When activated in the toolbar, the tool
-    resets the data bounds of the plot to their values when the plot was
-    initially created.
-
-    Optionally, the reset tool also resets the plat canvas dimensions to
-    their original size
+    The reset tool is an action. When activated in the toolbar, the tool resets
+    the data bounds of the plot to their values when the plot was initially
+    created.
 
     .. |reset_icon| image:: /_images/icons/Reset.png
         :height: 18pt
@@ -515,14 +513,14 @@ class TapTool(Tap):
 class CrosshairTool(Inspection):
     ''' *toolbar icon*: |crosshair_icon|
 
-    The crosshair tool is a passive inspector tool. It is generally on
-    at all times, but can be configured in the inspector's menu
-    associated with the *toolbar icon* shown above.
+    The crosshair tool is a passive inspector tool. It is generally on at all
+    times, but can be configured in the inspector's menu associated with the
+    *toolbar icon* shown above.
 
-    The crosshair tool draws a crosshair annotation over the plot,
-    centered on the current mouse position. The crosshair tool may be
-    configured to draw across only one dimension by setting the
-    ``dimension`` property to only ``width`` or ``height``.
+    The crosshair tool draws a crosshair annotation over the plot, centered on
+    the current mouse position. The crosshair tool may be configured to draw
+    across only one dimension by setting the ``dimension`` property to only
+    ``width`` or ``height``.
 
     .. |crosshair_icon| image:: /_images/icons/Crosshair.png
         :height: 18pt
@@ -530,10 +528,10 @@ class CrosshairTool(Inspection):
     '''
 
     dimensions = Enum(Dimensions, default="both", help="""
-    Which dimensions the crosshair tool is to track. By default, both a
-    vertical and horizontal line will be drawn. If only "width" is supplied,
-    only a horizontal line will be drawn. If only "height" is supplied,
-    only a vertical line will be drawn.
+    Which dimensions the crosshair tool is to track. By default, both vertical
+    and horizontal lines will be drawn. If only "width" is supplied, only a
+    horizontal line will be drawn. If only "height" is supplied, only a
+    vertical line will be drawn.
     """)
 
     line_color = Color(default="black", help="""
@@ -580,24 +578,27 @@ class CrosshairTool(Inspection):
 class BoxZoomTool(Drag):
     ''' *toolbar icon*: |box_zoom_icon|
 
-    The box zoom tool allows users to define a rectangular
-    region of a Plot to zoom to by dragging he mouse or a
-    finger over the plot region. The end of the drag
-    event indicates the selection region is ready.
+    The box zoom tool allows users to define a rectangular egion of a Plot to
+    zoom to by dragging he mouse or a finger over the plot region. The end of
+    the drag event indicates the selection region is ready.
 
     .. |box_zoom_icon| image:: /_images/icons/BoxZoom.png
         :height: 18pt
 
+    .. note::
+        ``BoxZoomTool`` is incompatible with ``GMapPlot`` due to the manner in
+        which Google Maps exert explicit control over aspect ratios. Adding
+        this tool to a ``GMapPlot`` will have no effect.
+
     '''
 
     dimensions = Enum(Dimensions, default="both", help="""
-    Which dimensions the zoom box is to be free in. By default,
-    users may freely draw zoom boxes with any dimensions. If only
-    "width" is supplied, the box will be constrained to span the entire
-    vertical space of the plot, only the horizontal dimension can be
-    controlled. If only "height" is supplied, the box will be constrained
-    to span the entire horizontal space of the plot, and the vertical
-    dimension can be controlled.
+    Which dimensions the zoom box is to be free in. By default, users may
+    freely draw zoom boxes with any dimensions. If only "width" is supplied,
+    the box will be constrained to span the entire vertical space of the plot,
+    only the horizontal dimension can be controlled. If only "height" is
+    supplied, the box will be constrained to span the entire horizontal space
+    of the plot, and the vertical dimension can be controlled.
     """)
 
     overlay = Instance(BoxAnnotation, default=DEFAULT_BOX_OVERLAY, help="""
@@ -631,10 +632,10 @@ class ZoomInTool(Action):
     '''
     # TODO ZoomInTool dimensions should probably be constrained to be the same as ZoomOutTool
     dimensions = Enum(Dimensions, default="both", help="""
-    Which dimensions the zoom-in tool is constrained to act in. By
-    default the zoom-in zoom tool will zoom in any dimension, but can be
-    configured to only zoom horizontally across the width of the plot, or
-    vertically across the height of the plot.
+    Which dimensions the zoom-in tool is constrained to act in. By default the
+    zoom-in zoom tool will zoom in any dimension, but can be configured to only
+    zoom horizontally across the width of the plot, or vertically across the
+    height of the plot.
     """)
 
     factor = Percent(default=0.1, help="""
@@ -652,10 +653,10 @@ class ZoomOutTool(Action):
 
     '''
     dimensions = Enum(Dimensions, default="both", help="""
-    Which dimensions the zoom-out tool is constrained to act in. By
-    default the zoom-out tool will zoom in any dimension, but can be
-    configured to only zoom horizontally across the width of the plot, or
-    vertically across the height of the plot.
+    Which dimensions the zoom-out tool is constrained to act in. By default the
+    zoom-out tool will zoom in any dimension, but can be configured to only
+    zoom horizontally across the width of the plot, or vertically across the
+    height of the plot.
     """)
 
     factor = Percent(default=0.1, help="""
@@ -665,10 +666,9 @@ class ZoomOutTool(Action):
 class BoxSelectTool(Drag):
     ''' *toolbar icon*: |box_select_icon|
 
-    The box selection tool allows users to make selections on a
-    Plot by indicating a rectangular region by dragging the
-    mouse or a finger over the plot region. The end of the drag
-    event indicates the selection region is ready.
+    The box selection tool allows users to make selections on a Plot by showing
+    a rectangular region by dragging the mouse or a finger over the plot area.
+    The end of the drag event indicates the selection region is ready.
 
     See :ref:`userguide_styling_selected_unselected_glyphs` for information
     on styling selected and unselected glyphs.
@@ -680,8 +680,8 @@ class BoxSelectTool(Drag):
     '''
 
     names = List(String, help="""
-    A list of names to query for. If set, only renderers that
-    have a matching value for their ``name`` attribute will be used.
+    A list of names to query for. If set, only renderers that have a matching
+    value for their ``name`` attribute will be used.
     """)
 
     renderers = Either(Auto, List(Instance(Renderer)), default="auto", help="""
@@ -690,18 +690,17 @@ class BoxSelectTool(Drag):
     """)
 
     select_every_mousemove = Bool(False, help="""
-    Whether a selection computation should happen on every mouse
-    event, or only once, when the selection region is completed. Default: False
+    Whether a selection computation should happen on every mouse event, or only
+    once, when the selection region is completed. Default: False
     """)
 
     dimensions = Enum(Dimensions, default="both", help="""
-    Which dimensions the box selection is to be free in. By default,
-    users may freely draw selections boxes with any dimensions. If only
-    "width" is supplied, the box will be constrained to span the entire
-    vertical space of the plot, only the horizontal dimension can be
-    controlled. If only "height" is supplied, the box will be constrained
-    to span the entire horizontal space of the plot, and the vertical
-    dimension can be controlled.
+    Which dimensions the box selection is to be free in. By default, users may
+    freely draw selections boxes with any dimensions. If only "width" is set,
+    the box will be constrained to span the entire vertical space of the plot,
+    only the horizontal dimension can be controlled. If only "height" is set,
+    the box will be constrained to span the entire horizontal space of the
+    plot, and the vertical dimension can be controlled.
     """)
 
     callback = Instance(Callback, help="""
@@ -736,19 +735,19 @@ class BoxSelectTool(Drag):
 class LassoSelectTool(Drag):
     ''' *toolbar icon*: |lasso_select_icon|
 
-    The lasso selection tool allows users to make selections on a
-    Plot by indicating a free-drawn "lasso" region by dragging the
-    mouse or a finger over the plot region. The end of the drag
-    event indicates the selection region is ready.
+    The lasso selection tool allows users to make selections on a Plot by
+    indicating a free-drawn "lasso" region by dragging the mouse or a finger
+    over the plot region. The end of the drag event indicates the selection
+    region is ready.
 
     See :ref:`userguide_styling_selected_unselected_glyphs` for information
     on styling selected and unselected glyphs.
 
     .. note::
-        Selections can be comprised of multiple regions, even those
-        made by different selection tools. Hold down the <<shift>> key
-        while making a selection to append the new selection to any
-        previous selection that might exist.
+        Selections can be comprised of multiple regions, even those made by
+        different selection tools. Hold down the <<shift>> key while making a
+        selection to append the new selection to any previous selection that
+        might exist.
 
     .. |lasso_select_icon| image:: /_images/icons/LassoSelect.png
         :height: 18pt
@@ -756,23 +755,23 @@ class LassoSelectTool(Drag):
     '''
 
     names = List(String, help="""
-    A list of names to query for. If set, only renderers that
-    have a matching value for their ``name`` attribute will be used.
+    A list of names to query for. If set, only renderers that have a matching
+    value for their ``name`` attribute will be used.
     """)
 
     renderers = Either(Auto, List(Instance(Renderer)), default="auto", help="""
-    An explicit list of renderers to hit test against. If unset,
-    defaults to all renderers on a plot.
+    An explicit list of renderers to hit test against. If unset, defaults to
+    all renderers on a plot.
     """)
 
     select_every_mousemove = Bool(True, help="""
-    Whether a selection computation should happen on every mouse
-    event, or only once, when the selection region is completed. Default: True
+    Whether a selection computation should happen on every mouse event, or only
+    once, when the selection region is completed.
     """)
 
     callback = Instance(Callback, help="""
-    A callback to run in the browser on every selection of a lasso area.
-    The ``cb_data`` parameter that is available to the Callback code will contain
+    A callback to run in the browser on every selection of a lasso area. The
+    ``cb_data`` parameter that is available to the Callback code will contain
     one ``LassoSelectTool``-specific field:
 
     :geometry: object containing the coordinates of the lasso area
@@ -806,18 +805,18 @@ class PolySelectTool(Tap):
     '''
 
     names = List(String, help="""
-    A list of names to query for. If set, only renderers that
-    have a matching value for their ``name`` attribute will be used.
+    A list of names to query for. If set, only renderers that  have a matching
+    value for their ``name`` attribute will be used.
     """)
 
     renderers = Either(Auto, List(Instance(Renderer)), default="auto", help="""
-    An explicit list of renderers to hit test against. If unset,
-    defaults to all renderers on a plot.
+    An explicit list of renderers to hit test against. If unset, defaults to
+    all renderers on a plot.
     """)
 
     callback = Instance(Callback, help="""
-    A callback to run in the browser on completion of drawing a polygon.
-    The ``cb_data`` parameter that is available to the Callback code will contain
+    A callback to run in the browser on completion of drawing a polygon. The
+    ``cb_data`` parameter that is available to the Callback code will contain
     one PolySelectTool-specific field:
 
     :geometry: object containing the coordinates of the polygon
@@ -884,7 +883,7 @@ def from_py_func(cls, code):
         ''' Create a ``CustomJSHover`` instance from a Python functions. The
         function is translated to JavaScript using PScript.
 
-        The python functions must have no positional arguments. It's
+        The python functions must have no positional arguments. It is
         possible to pass Bokeh models (e.g. a ``ColumnDataSource``) as keyword
         arguments to the functions.
 
@@ -934,13 +933,13 @@ def pscript_compile(code):
 
     @classmethod
     def from_coffeescript(cls, code, args={}):
-        ''' Create a CustomJSHover instance from a CoffeeScript snippet.
-        The function bodies are translated to JavaScript functions using
-        node and therefore require return statements.
+        ''' Create a CustomJSHover instance from a CoffeeScript snippet. The
+        function bodies are translated to JavaScript functions using node and
+        therefore require return statements.
 
-        The ``code`` snippet namespace will contain the variable ``value``
-        (the untransformed value) at render time as well as ``format`` and
-        ``special_vars`` as described in the class description.
+        The ``code`` snippet namespace will contain the variable ``value`` (the
+        untransformed value) at render time as well as ``special_vars`` and
+        ``format`` as described in the class description.
 
         Example:
 
@@ -963,9 +962,9 @@ def from_coffeescript(cls, code, args={}):
         return cls(code=compiled.code, args=args)
 
     args = Dict(String, Instance(Model), help="""
-    A mapping of names to Bokeh plot objects. These objects are made
-    available to the callback code snippet as the values of named
-    parameters to the callback.
+    A mapping of names to Bokeh plot objects. These objects are made available
+    to the callback code snippet as the values of named parameters to the
+    callback.
     """)
 
     code = String(default="", help="""
@@ -1004,15 +1003,15 @@ def from_coffeescript(cls, code, args={}):
 class HoverTool(Inspection):
     ''' *toolbar icon*: |crosshair_icon|
 
-    The hover tool is a passive inspector tool. It is generally on at
-    all times, but can be configured in the inspector's menu associated
-    with the *toolbar icon* shown above.
+    The hover tool is a passive inspector tool. It is generally on at all
+    times, but can be configured in the inspector's menu associated with the
+    *toolbar icon* shown above.
 
-    By default, the hover tool displays informational tooltips whenever
-    the cursor is directly over a glyph. The data to show comes from the
-    glyph's data source, and what is to be displayed is configurable with
-    the ``tooltips`` attribute that maps display names to columns in the
-    data source, or to special known variables.
+    By default, the hover tool displays informational tooltips whenever the
+    cursor is directly over a glyph. The data to show comes from the glyph's
+    data source, and what to display is configurable with the ``tooltips``
+    property that maps display names to columns in the data source, or to
+    special known variables.
 
     Here is an example of how to configure and use the hover tool::
 
@@ -1063,13 +1062,13 @@ class HoverTool(Inspection):
     '''
 
     names = List(String, help="""
-    A list of names to query for. If set, only renderers that
-    have a matching value for their ``name`` attribute will be used.
+    A list of names to query for. If set, only renderers that have a matching
+    value for their ``name`` attribute will be used.
     """)
 
     renderers = Either(Auto, List(Instance(Renderer)), default="auto", help="""
-    An explicit list of renderers to hit test against. If unset,
-    defaults to all renderers on a plot.
+    An explicit list of renderers to hit test against. If unset, defaults to
+    all renderers on a plot.
     """)
 
     callback = Instance(Callback, help="""
@@ -1285,8 +1284,8 @@ class EditTool(Gesture):
     """)
 
     renderers = List(Instance(Renderer), help="""
-    An explicit list of renderers corresponding to scatter glyphs
-    that may be edited.
+    An explicit list of renderers corresponding to scatter glyphs that may
+    be edited.
     """)
 
 class BoxEditTool(EditTool, Drag, Tap):
@@ -1298,52 +1297,49 @@ class BoxEditTool(EditTool, Drag, Tap):
     explicitly as a list. When drawing a new box the data will always be added
     to the ``ColumnDataSource`` on the first supplied renderer.
 
-    The tool will automatically modify the columns on the data source
-    corresponding to the ``x``, ``y``, ``width`` and ``height`` values
-    of the glyph. Any additional columns in the data source will be
-    padded with the declared ``empty_value``, when adding a new box.
+    The tool will modify the columns on the data source corresponding to the
+    ``x``, ``y``, ``width`` and ``height`` values of the glyph. Any additional
+    columns in the data source will be padded with ``empty_value``, when adding
+    a new box.
 
     The supported actions include:
 
-    * Add box: Hold shift then click and drag anywhere on the plot or
-      double tap once to start drawing, move the mouse and double tap
-      again to finish drawing.
+    * Add box: Hold shift then click and drag anywhere on the plot or double
+      tap once to start drawing, move the mouse and double tap again to finish
+      drawing.
 
-    * Move box: Click and drag an existing box, the box will be
-      dropped once you let go of the mouse button.
+    * Move box: Click and drag an existing box, the box will be dropped once
+      you let go of the mouse button.
 
-    * Delete box: Tap a box to select it then press <<backspace>> key
-      while the mouse is within the plot area.
+    * Delete box: Tap a box to select it then press <<backspace>> key while the
+      mouse is within the plot area.
 
     To **Move** or **Delete** multiple boxes at once:
 
-    * Move selection: Select box(es) with <<shift>>+tap (or another
-      selection tool) then drag anywhere on the plot. Selecting and
-      then dragging on a specific box will move both.
+    * Move selection: Select box(es) with <<shift>>+tap (or another selection
+      tool) then drag anywhere on the plot. Selecting and then dragging on a
+      specific box will move both.
 
-    * Delete selection: Select box(es) with <<shift>>+tap (or another
-      selection tool) then press <<backspace>> while the mouse is
-      within the plot area.
+    * Delete selection: Select box(es) with <<shift>>+tap (or another selection
+      tool) then press <<backspace>> while the mouse is within the plot area.
 
     .. |box_edit_icon| image:: /_images/icons/BoxEdit.png
         :height: 18pt
     '''
 
     dimensions = Enum(Dimensions, default="both", help="""
-    Which dimensions the box drawing is to be free in. By default,
-    users may freely draw boxes with any dimensions. If only "width"
-    is supplied, the box will be constrained to span the entire
-    vertical space of the plot, only the horizontal dimension can be
-    controlled. If only "height" is supplied, the box will be
-    constrained to span the entire horizontal space of the plot, and
-    the vertical dimension can be controlled.
+    Which dimensions the box drawing is to be free in. By default, users may
+    freely draw boxes with any dimensions. If only "width" is set, the box will
+    be constrained to span the entire vertical space of the plot, only the
+    horizontal dimension can be controlled. If only "height" is set, the box
+    will be constrained to span the entire horizontal space of the plot, and the
+    vertical dimension can be controlled.
     """)
 
     num_objects = Int(default=0, help="""
-    Defines a limit on the number of boxes that can be drawn. By
-    default there is no limit on the number of objects, but if enabled
-    the oldest drawn box will be dropped to make space for the new box
-    being added.
+    Defines a limit on the number of boxes that can be drawn. By default there
+    is no limit on the number of objects, but if enabled the oldest drawn box
+    will be dropped to make space for the new box being added.
     """)
 
     @error(INCOMPATIBLE_BOX_EDIT_RENDERER)
@@ -1359,17 +1355,17 @@ def _check_compatible_renderers(self):
 class PointDrawTool(EditTool, Drag, Tap):
     ''' *toolbar icon*: |point_draw_icon|
 
-    The PointDrawTool allows adding, dragging and deleting point-like
-    glyphs (of ``XYGlyph`` type) on one or more renderers by editing the
+    The PointDrawTool allows adding, dragging and deleting point-like glyphs
+    (i.e subclasses of``XYGlyph``) on one or more renderers by editing the
     underlying ``ColumnDataSource`` data. Like other drawing tools, the
-    renderers that are to be edited must be supplied explicitly as a list.
-    Any newly added points will be inserted on the ``ColumnDataSource`` of
-    the first supplied renderer.
+    renderers that are to be edited must be supplied explicitly as a list. Any
+    newly added points will be inserted on the ``ColumnDataSource`` of the
+    first supplied renderer.
 
-    The tool will automatically modify the columns on the data source
-    corresponding to the ``x`` and ``y`` values of the glyph. Any additional
-    columns in the data source will be padded with the given ``empty_value``
-    when adding a new point.
+    The tool will modify the columns on the data source corresponding to the
+    ``x`` and ``y`` values of the glyph. Any additional columns in the data
+    source will be padded with the given ``empty_value`` when adding a new
+    point.
 
     .. note::
         The data source updates will trigger data change events continuously
@@ -1392,16 +1388,17 @@ class PointDrawTool(EditTool, Drag, Tap):
     '''
 
     add = Bool(default=True, help="""
-    Enables adding of new points on tap events.""")
+    Enables adding of new points on tap events.
+    """)
 
     drag = Bool(default=True, help="""
-    Enables dragging of existing points on pan events.""")
+    Enables dragging of existing points on pan events.
+    """)
 
     num_objects = Int(default=0, help="""
-    Defines a limit on the number of points that can be drawn. By
-    default there is no limit on the number of objects, but if enabled
-    the oldest drawn point will be dropped to make space for the new
-    point.
+    Defines a limit on the number of points that can be drawn. By default there
+    is no limit on the number of objects, but if enabled the oldest drawn point
+    will be dropped to make space for the new point.
     """)
 
     @error(INCOMPATIBLE_POINT_DRAW_RENDERER)
@@ -1417,54 +1414,51 @@ def _check_compatible_renderers(self):
 class PolyDrawTool(EditTool, Drag, Tap):
     ''' *toolbar icon*: |poly_draw_icon|
 
-    The PolyDrawTool allows drawing, selecting and deleting
-    ``Patches`` and ``MultiLine`` glyphs on one or more renderers by
-    editing the underlying ``ColumnDataSource`` data. Like other drawing
-    tools, the renderers that are to be edited must be supplied
-    explicitly as a list.
+    The PolyDrawTool allows drawing, selecting and deleting ``Patches`` and
+    ``MultiLine`` glyphs on one or more renderers by editing the underlying
+    ``ColumnDataSource`` data. Like other drawing tools, the renderers that
+    are to be edited must be supplied explicitly.
 
-    The tool will automatically modify the columns on the data source
-    corresponding to the ``xs`` and ``ys`` values of the glyph. Any
-    additional columns in the data source will be padded with the
-    declared ``empty_value``, when adding a new point.
+    The tool will modify the columns on the data source corresponding to the
+    ``xs`` and ``ys`` values of the glyph. Any additional columns in the data
+    source will be padded with the declared ``empty_value``, when adding a new
+    point.
 
-    If a ``vertex_renderer`` with an point-like glyph is supplied the
-    ``PolyDrawTool`` will use it to display the vertices of the
-    multi-lines/patches on all supplied renderers. This also enables
-    the ability to snap to existing vertices while drawing.
+    If a ``vertex_renderer`` with an point-like glyph is supplied then the
+    ``PolyDrawTool`` will use it to display the vertices of the multi-lines or
+    patches on all supplied renderers. This also enables the ability to snap
+    to existing vertices while drawing.
 
     The supported actions include:
 
-    * Add patch/multi-line: Double tap to add the first vertex, then
-      use tap to add each subsequent vertex, to finalize the draw
-      action double tap to insert the final vertex or press the <<esc>
-      key.
+    * Add patch or multi-line: Double tap to add the first vertex, then use tap
+      to add each subsequent vertex, to finalize the draw action double tap to
+      insert the final vertex or press the <<esc> key.
 
-    * Move patch/multi-line: Tap and drag an existing
-      patch/multi-line, the point will be dropped once you let go of
-      the mouse button.
+    * Move patch or ulti-line: Tap and drag an existing patch/multi-line, the
+      point will be dropped once you let go of the mouse button.
 
-    * Delete patch/multi-line: Tap a patch/multi-line to select it
-      then press <<backspace>> key while the mouse is within the plot
-      area.
+    * Delete patch or multi-line: Tap a patch/multi-line to select it then
+      press <<backspace>> key while the mouse is within the plot area.
 
     .. |poly_draw_icon| image:: /_images/icons/PolyDraw.png
         :height: 18pt
     '''
 
     drag = Bool(default=True, help="""
-    Enables dragging of existing patches and multi-lines on pan events.""")
+    Enables dragging of existing patches and multi-lines on pan events.
+    """)
 
     num_objects = Int(default=0, help="""
-    Defines a limit on the number of patches or multi-lines that can
-    be drawn. By default there is no limit on the number of objects,
-    but if enabled the oldest drawn patch or multi-line will be
-    dropped to make space for the new patch or multi-line.
+    Defines a limit on the number of patches or multi-lines that can be drawn.
+    By default there is no limit on the number of objects, but if enabled the
+    oldest drawn patch or multi-line will be dropped to make space for the new
+    patch or multi-line.
     """)
 
     vertex_renderer = Instance(GlyphRenderer, help="""
-    The renderer used to render the vertices of a selected line or
-    polygon.""")
+    The renderer used to render the vertices of a selected line or polygon.
+    """)
 
     @error(INCOMPATIBLE_POLY_DRAW_RENDERER)
     def _check_compatible_renderers(self):
@@ -1490,28 +1484,27 @@ class FreehandDrawTool(EditTool, Drag, Tap):
     Allows freehand drawing of ``Patches`` and ``MultiLine`` glyphs. The glyph
     to draw may be defined via the ``renderers`` property.
 
-    The tool will automatically modify the columns on the data source
-    corresponding to the ``xs`` and ``ys`` values of the glyph. Any
-    additional columns in the data source will be padded with the
-    declared ``empty_value``, when adding a new point.
+    The tool will modify the columns on the data source corresponding to the
+    ``xs`` and ``ys`` values of the glyph. Any additional columns in the data
+    source will be padded with the declared ``empty_value``, when adding a new
+    point.
 
     The supported actions include:
 
     * Draw vertices: Click and drag to draw a line
 
-    * Delete patch/multi-line: Tap a patch/multi-line to select it
-      then press <<backspace>> key while the mouse is within the plot
-      area.
+    * Delete patch/multi-line: Tap a patch/multi-line to select it then press
+      <<backspace>> key while the mouse is within the plot area.
 
     .. |freehand_draw_icon| image:: /_images/icons/FreehandDraw.png
         :height: 18pt
     '''
 
     num_objects = Int(default=0, help="""
-    Defines a limit on the number of patches or multi-lines that can
-    be drawn. By default there is no limit on the number of objects,
-    but if enabled the oldest drawn patch or multi-line will be
-    overwritten when the limit is reached.
+    Defines a limit on the number of patches or multi-lines that can be drawn.
+    By default there is no limit on the number of objects, but if enabled the
+    oldest drawn patch or multi-line will be overwritten when the limit is
+    reached.
     """)
 
     @error(INCOMPATIBLE_POLY_DRAW_RENDERER)
@@ -1527,31 +1520,29 @@ def _check_compatible_renderers(self):
 class PolyEditTool(EditTool, Drag, Tap):
     ''' *toolbar icon*: |poly_edit_icon|
 
-    The PolyEditTool allows editing the vertices of one or more
-    ``Patches`` or ``MultiLine`` glyphs. The glyphs to be edited can
-    be defined via the ``renderers`` property and the renderer for the
-    vertices can be defined via the ``vertex_renderer``, which must
-    render a point-like Glyph (of ``XYGlyph`` type).
+    The PolyEditTool allows editing the vertices of one or more ``Patches`` or
+    ``MultiLine`` glyphs. Glyphs to be edited are defined via the ``renderers``
+    property and a renderer for the vertices is set via the ``vertex_renderer``
+    property (must render a point-like Glyph (a subclass of ``XYGlyph``).
 
-    The tool will automatically modify the columns on the data source
-    corresponding to the ``xs`` and ``ys`` values of the glyph. Any
-    additional columns in the data source will be padded with the
-    declared ``empty_value``, when adding a new point.
+    The tool will modify the columns on the data source corresponding to the
+    ``xs`` and ``ys`` values of the glyph. Any additional columns in the data
+    source will be padded with the declared``empty_value``, when adding a new
+    point.
 
     The supported actions include:
 
     * Show vertices: Double tap an existing patch or multi-line
 
-    * Add vertex: Double tap an existing vertex to select it, the tool
-      will draw the next point, to add it tap in a new location. To
-      finish editing and add a point double tap otherwise press the
-      <<esc> key to cancel.
+    * Add vertex: Double tap an existing vertex to select it, the tool will
+      draw the next point, to add it tap in a new location. To finish editing
+      and add a point double tap otherwise press the <<esc> key to cancel.
 
-    * Move vertex: Drag an existing vertex and let go of the mouse
-      button to release it.
+    * Move vertex: Drag an existing vertex and let go of the mouse button to
+      release it.
 
-    * Delete vertex: After selecting one or more vertices press
-      <<backspace>> while the mouse cursor is within the plot area.
+    * Delete vertex: After selecting one or more vertices press <<backspace>>
+      while the mouse cursor is within the plot area.
 
     .. |poly_edit_icon| image:: /_images/icons/PolyEdit.png
         :height: 18pt


Test patch: