# Buggy code
def prep_ticks(ax, index, ax_type, props):
    """Prepare axis obj belonging to axes obj.

    positional arguments:
    ax - the mpl axes instance
    index - the index of the axis in `props`
    ax_type - 'x' or 'y' (for now)
    props - an mplexporter poperties dictionary

    """
    axis_dict = dict()
    if ax_type == "x":
        axis = ax.get_xaxis()
    elif ax_type == "y":
        axis = ax.get_yaxis()
    else:
        return dict()  # whoops!

    scale = props["axes"][index]["scale"]
    if scale == "linear":
        # get tick location information
        try:
            tickvalues = props["axes"][index]["tickvalues"]
            tick0 = tickvalues[0]
            dticks = [
                round(tickvalues[i] - tickvalues[i - 1], 12)
                for i in range(1, len(tickvalues) - 1)
            ]
            if all([dticks[i] == dticks[i - 1] for i in range(1, len(dticks) - 1)]):
                dtick = tickvalues[1] - tickvalues[0]
            else:
                warnings.warn(
                    "'linear' {0}-axis tick spacing not even, "
                    "ignoring mpl tick formatting.".format(ax_type)
                )
                raise TypeError
        except (IndexError, TypeError):
            axis_dict["nticks"] = props["axes"][index]["nticks"]
        else:
            axis_dict["tick0"] = tick0
            axis_dict["dtick"] = dtick
            axis_dict["tickmode"] = False
    elif scale == "log":
        try:
            axis_dict["tick0"] = props["axes"][index]["tickvalues"][0]
            axis_dict["dtick"] = (
                props["axes"][index]["tickvalues"][1]
                - props["axes"][index]["tickvalues"][0]
            )
            axis_dict["tickmode"] = False
        except (IndexError, TypeError):
            axis_dict = dict(nticks=props["axes"][index]["nticks"])
        base = axis.get_transform().base
        if base == 10:
            if ax_type == "x":
                axis_dict["range"] = [
                    math.log10(props["xlim"][0]),
                    math.log10(props["xlim"][1]),
                ]
            elif ax_type == "y":
                axis_dict["range"] = [
                    math.log10(props["ylim"][0]),
                    math.log10(props["ylim"][1]),
                ]
        else:
            axis_dict = dict(range=None, type="linear")
            warnings.warn(
                "Converted non-base10 {0}-axis log scale to 'linear'".format(ax_type)
            )
    else:
        return dict()
    # get tick label formatting information
    formatter = axis.get_major_formatter().__class__.__name__
    if ax_type == "x" and "DateFormatter" in formatter:
        axis_dict["type"] = "date"
        try:
            axis_dict["tick0"] = mpl_dates_to_datestrings(axis_dict["tick0"], formatter)
        except KeyError:
            pass
        finally:
            axis_dict.pop("dtick", None)
            axis_dict.pop("tickmode", None)
            axis_dict["range"] = mpl_dates_to_datestrings(props["xlim"], formatter)

    if formatter == "LogFormatterMathtext":
        axis_dict["exponentformat"] = "e"
    return axis_dict


# Traceback (ValueError)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-11-523d3e17715d> in <module>()
----> 1 ply.iplot_mpl(g.fig)

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/plotly/offline/offline.py in iplot_mpl(mpl_fig, resize, strip_style, verbose, show_link, link_text, validate, image, image_filename, image_height, image_width)
682     ```
683     """
--> 684     plotly_plot = tools.mpl_to_plotly(mpl_fig, resize, strip_style, verbose)
685     return iplot(plotly_plot, show_link, link_text, validate,
686                  image=image, filename=image_filename,

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/plotly/tools.py in mpl_to_plotly(fig, resize, strip_style, verbose)
463     if matplotlylib:
464         renderer = matplotlylib.PlotlyRenderer()
--> 465         matplotlylib.Exporter(renderer).run(fig)
466         if resize:
467             renderer.resize()

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/plotly/matplotlylib/mplexporter/exporter.py in run(self, fig)
47             import matplotlib.pyplot as plt
48             plt.close(fig)
---> 49         self.crawl_fig(fig)
50
51     @staticmethod

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/plotly/matplotlylib/mplexporter/exporter.py in crawl_fig(self, fig)
114                                        props=utils.get_figure_properties(fig)):
115             for ax in fig.axes:
--> 116                 self.crawl_ax(ax)
117
118     def crawl_ax(self, ax):

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/plotly/matplotlylib/mplexporter/exporter.py in crawl_ax(self, ax)
119         """Crawl the axes and process all elements within"""
120         with self.renderer.draw_axes(ax=ax,
--> 121                                      props=utils.get_axes_properties(ax)):
122             for line in ax.lines:
123                 self.draw_line(ax, line)

~/anaconda3/envs/mlapp/lib/python3.6/contextlib.py in __enter__(self)
79     def __enter__(self):
80         try:
---> 81             return next(self.gen)
82         except StopIteration:
83             raise RuntimeError("generator didn't yield") from None

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/plotly/matplotlylib/mplexporter/renderers/base.py in draw_axes(self, ax, props)
53         self._current_ax = ax
54         self._ax_props = props
---> 55         self.open_axes(ax=ax, props=props)
56         yield
57         self.close_axes(ax=ax)

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/plotly/matplotlylib/renderer.py in open_axes(self, ax, props)
163             x_bounds=self.mpl_x_bounds,
164             y_bounds=self.mpl_y_bounds)
--> 165         xaxis.update(mpl_xaxis)
166         yaxis.update(mpl_yaxis)
167         bottom_spine = mpltools.get_spine_visible(ax, 'bottom')

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/plotly/basedatatypes.py in update(self, dict1, **kwargs)
2854                 BaseFigure._perform_update(self, kwargs)
2855         else:
-> 2856             BaseFigure._perform_update(self, dict1)
2857             BaseFigure._perform_update(self, kwargs)
2858

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/plotly/basedatatypes.py in _perform_update(plotly_obj, update_obj)
2138                 else:
2139                     # Assign non-compound value
-> 2140                     plotly_obj[key] = val
2141
2142         elif isinstance(plotly_obj, tuple):

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/plotly/basedatatypes.py in __setitem__(self, prop, value)
2663             # ### Handle simple property ###
2664             else:
-> 2665                 self._set_prop(prop, value)
2666
2667         # Handle non-scalar case

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/plotly/basedatatypes.py in _set_prop(self, prop, val)
2893         # ------------
2894         validator = self._validators.get(prop)
-> 2895         val = validator.validate_coerce(val)
2896
2897         # val is None

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/_plotly_utils/basevalidators.py in validate_coerce(self, v)
486             v = self.perform_replacemenet(v)
487             if not self.in_values(v):
--> 488                 self.raise_invalid_val(v)
489         return v
490

~/anaconda3/envs/mlapp/lib/python3.6/site-packages/_plotly_utils/basevalidators.py in raise_invalid_val(self, v)
214             typ=type_str(v),
215             v=repr(v),
--> 216             valid_clr_desc=self.description()))
217
218     def raise_invalid_elements(self, invalid_els):

ValueError:
Invalid value of type 'builtins.bool' received for the 'tickmode' property of layout.xaxis
Received value: False

The 'tickmode' property is an enumeration that may be specified as:
- One of the following enumeration values:
['auto', 'linear', 'array']

# Fixed code
def prep_ticks(ax, index, ax_type, props):
    """Prepare axis obj belonging to axes obj.

    positional arguments:
    ax - the mpl axes instance
    index - the index of the axis in `props`
    ax_type - 'x' or 'y' (for now)
    props - an mplexporter poperties dictionary

    """
    axis_dict = dict()
    if ax_type == "x":
        axis = ax.get_xaxis()
    elif ax_type == "y":
        axis = ax.get_yaxis()
    else:
        return dict()  # whoops!

    scale = props["axes"][index]["scale"]
    if scale == "linear":
        # get tick location information
        try:
            tickvalues = props["axes"][index]["tickvalues"]
            tick0 = tickvalues[0]
            dticks = [
                round(tickvalues[i] - tickvalues[i - 1], 12)
                for i in range(1, len(tickvalues) - 1)
            ]
            if all([dticks[i] == dticks[i - 1] for i in range(1, len(dticks) - 1)]):
                dtick = tickvalues[1] - tickvalues[0]
            else:
                warnings.warn(
                    "'linear' {0}-axis tick spacing not even, "
                    "ignoring mpl tick formatting.".format(ax_type)
                )
                raise TypeError
        except (IndexError, TypeError):
            axis_dict["nticks"] = props["axes"][index]["nticks"]
        else:
            axis_dict["tick0"] = tick0
            axis_dict["dtick"] = dtick
            axis_dict["tickmode"] = None
    elif scale == "log":
        try:
            axis_dict["tick0"] = props["axes"][index]["tickvalues"][0]
            axis_dict["dtick"] = (
                props["axes"][index]["tickvalues"][1]
                - props["axes"][index]["tickvalues"][0]
            )
            axis_dict["tickmode"] = None
        except (IndexError, TypeError):
            axis_dict = dict(nticks=props["axes"][index]["nticks"])
        base = axis.get_transform().base
        if base == 10:
            if ax_type == "x":
                axis_dict["range"] = [
                    math.log10(props["xlim"][0]),
                    math.log10(props["xlim"][1]),
                ]
            elif ax_type == "y":
                axis_dict["range"] = [
                    math.log10(props["ylim"][0]),
                    math.log10(props["ylim"][1]),
                ]
        else:
            axis_dict = dict(range=None, type="linear")
            warnings.warn(
                "Converted non-base10 {0}-axis log scale to 'linear'".format(ax_type)
            )
    else:
        return dict()
    # get tick label formatting information
    formatter = axis.get_major_formatter().__class__.__name__
    if ax_type == "x" and "DateFormatter" in formatter:
        axis_dict["type"] = "date"
        try:
            axis_dict["tick0"] = mpl_dates_to_datestrings(axis_dict["tick0"], formatter)
        except KeyError:
            pass
        finally:
            axis_dict.pop("dtick", None)
            axis_dict.pop("tickmode", None)
            axis_dict["range"] = mpl_dates_to_datestrings(props["xlim"], formatter)

    if formatter == "LogFormatterMathtext":
        axis_dict["exponentformat"] = "e"
    return axis_dict