diff --git a/circle.yml b/circle.yml index 994caf4d8cf..3c146d51ecc 100644 --- a/circle.yml +++ b/circle.yml @@ -2,7 +2,7 @@ machine: environment: - PLOTLY_PACKAGE_ROOT: /home/ubuntu/python-api + PLOTLY_PACKAGE_ROOT: /home/ubuntu/${CIRCLE_PROJECT_REPONAME} PLOTLY_CONFIG_DIR: ${HOME}/.plotly PLOTLY_PYTHON_VERSIONS: 2.7.8 3.3.3 3.4.1 PLOTLY_CORE_REQUIREMENTS_FILE: ${PLOTLY_PACKAGE_ROOT}/requirements.txt diff --git a/circle/test.sh b/circle/test.sh index c5f64dc0ce1..9f5c4451e39 100644 --- a/circle/test.sh +++ b/circle/test.sh @@ -41,7 +41,7 @@ for version in ${PLOTLY_PYTHON_VERSIONS[@]}; do error_exit "${SIG} ${LINENO}: can't import plotly package" echo "${SIG} Running tests for Python ${version} as user '$(whoami)'." - nosetests -x plotly/tests || + nosetests -x -a '!matplotlib' plotly/tests || error_exit "${SIG} ${LINENO}: test suite failed for Python ${version}" done diff --git a/optional-requirements.txt b/optional-requirements.txt index 2f609e087d0..f1fd52bf3e1 100644 --- a/optional-requirements.txt +++ b/optional-requirements.txt @@ -9,13 +9,13 @@ numpy ## matplotlylib dependencies ## -matplotlib==1.3.1 +# matplotlib==1.3.1 ## testing dependencies ## nose==1.3.3 ## ipython dependencies ## -ipython[all] +ipython[all]==3.0.0 ## pandas deps for some matplotlib functionality ## pandas diff --git a/plotly/graph_reference/default-schema.json b/plotly/graph_reference/default-schema.json index 5e71172090f..e62991014f0 100644 --- a/plotly/graph_reference/default-schema.json +++ b/plotly/graph_reference/default-schema.json @@ -4737,7 +4737,7 @@ "valType": "color" }, "outliercolor": { - "description": "Sets the border line color of the outlier sample points.", + "description": "Sets the border line color of the outlier sample points. Defaults to marker.color", "role": "style", "valType": "color" }, @@ -4769,7 +4769,7 @@ }, "outliercolor": { "description": "Sets the color of the outlier sample points.", - "dflt": "rgba(0,0,0,0)", + "dflt": "rgba(0, 0, 0, 0)", "role": "style", "valType": "color" }, diff --git a/plotly/matplotlylib/mplexporter/tests/test_basic.py b/plotly/matplotlylib/mplexporter/tests/test_basic.py index 25099ae77c2..bc6dc65f20c 100644 --- a/plotly/matplotlylib/mplexporter/tests/test_basic.py +++ b/plotly/matplotlylib/mplexporter/tests/test_basic.py @@ -1,14 +1,20 @@ -from ..exporter import Exporter -from ..renderers import FakeRenderer, FullFakeRenderer +# TODO: matplotlib-build-wip +from nose.plugins.attrib import attr +from plotly.tools import _matplotlylib_imported -import matplotlib -matplotlib.use('Agg') -import matplotlib.pyplot as plt +if _matplotlylib_imported: + from ..exporter import Exporter + from ..renderers import FakeRenderer, FullFakeRenderer -import numpy as np -from numpy.testing import assert_warns + import matplotlib + matplotlib.use('Agg') + import matplotlib.pyplot as plt + import numpy as np + from numpy.testing import assert_warns + +@attr('matplotlib') def fake_renderer_output(fig, Renderer): renderer = Renderer() exporter = Exporter(renderer) @@ -16,11 +22,13 @@ def fake_renderer_output(fig, Renderer): return renderer.output +@attr('matplotlib') def _assert_output_equal(text1, text2): for line1, line2 in zip(text1.strip().split(), text2.strip().split()): assert line1 == line2 +@attr('matplotlib') def test_lines(): fig, ax = plt.subplots() ax.plot(range(20), '-k') @@ -44,6 +52,7 @@ def test_lines(): """) +@attr('matplotlib') def test_markers(): fig, ax = plt.subplots() ax.plot(range(2), 'ok') @@ -68,6 +77,7 @@ def test_markers(): """) +@attr('matplotlib') def test_path_collection(): fig, ax = plt.subplots() ax.scatter(range(3), range(3)) @@ -93,6 +103,7 @@ def test_path_collection(): """) +@attr('matplotlib') def test_text(): fig, ax = plt.subplots() ax.set_xlabel("my x label") @@ -113,6 +124,7 @@ def test_text(): """) +@attr('matplotlib') def test_path(): fig, ax = plt.subplots() ax.add_patch(plt.Circle((0, 0), 1)) @@ -129,6 +141,7 @@ def test_path(): """) +@attr('matplotlib') def test_multiaxes(): fig, ax = plt.subplots(2) ax[0].plot(range(4)) @@ -147,6 +160,7 @@ def test_multiaxes(): """) +@attr('matplotlib') def test_image(): np.random.seed(0) # image size depends on the seed fig, ax = plt.subplots() @@ -163,6 +177,7 @@ def test_image(): """) +@attr('matplotlib') def test_legend(): fig, ax = plt.subplots() ax.plot([1,2,3], label='label') @@ -178,6 +193,8 @@ def test_legend(): closing figure """) + +@attr('matplotlib') def test_legend_dots(): fig, ax = plt.subplots() ax.plot([1,2,3], label='label') @@ -200,8 +217,9 @@ def test_legend_dots(): closing figure """) + +@attr('matplotlib') def test_blended(): fig, ax = plt.subplots() ax.axvline(0) assert_warns(UserWarning, fake_renderer_output, fig, FakeRenderer) - diff --git a/plotly/matplotlylib/mplexporter/tests/test_utils.py b/plotly/matplotlylib/mplexporter/tests/test_utils.py index 20b7aaf5ed1..9105f3cc0db 100644 --- a/plotly/matplotlylib/mplexporter/tests/test_utils.py +++ b/plotly/matplotlylib/mplexporter/tests/test_utils.py @@ -1,8 +1,13 @@ -from numpy.testing import assert_allclose, assert_equal -import matplotlib.pyplot as plt -from .. import utils +# TODO: matplotlib-build-wip +from nose.plugins.attrib import attr +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + from numpy.testing import assert_allclose, assert_equal + import matplotlib.pyplot as plt + from .. import utils +@attr('matplotlib') def test_path_data(): circle = plt.Circle((0, 0), 1) vertices, codes = utils.SVG_path(circle.get_path()) diff --git a/plotly/tests/test_core/test_graph_objs/nose_tools.py b/plotly/tests/test_core/test_graph_objs/nose_tools.py deleted file mode 100644 index 00f39e0fbd9..00000000000 --- a/plotly/tests/test_core/test_graph_objs/nose_tools.py +++ /dev/null @@ -1,67 +0,0 @@ -from __future__ import absolute_import - -from numbers import Number as Num - -import matplotlib -# Force matplotlib to not use any Xwindows backend. -matplotlib.use('Agg') - -from plotly.matplotlylib import Exporter, PlotlyRenderer - - -def compare_dict(dict1, dict2, equivalent=True, msg='', tol=10e-8): - for key in dict1: - if key not in dict2: - return (False, - "{0} should be {1}".format( - list(dict1.keys()), list(dict2.keys()))) - for key in dict1: - if isinstance(dict1[key], dict): - equivalent, msg = compare_dict(dict1[key], - dict2[key], - tol=tol) - elif isinstance(dict1[key], Num) and isinstance(dict2[key], Num): - if not comp_nums(dict1[key], dict2[key], tol): - return False, "['{0}'] = {1} should be {2}".format(key, - dict1[key], - dict2[key]) - elif is_num_list(dict1[key]) and is_num_list(dict2[key]): - if not comp_num_list(dict1[key], dict2[key], tol): - return False, "['{0}'] = {1} should be {2}".format(key, - dict1[key], - dict2[key]) - elif not (dict1[key] == dict2[key]): - return False, "['{0}'] = {1} should be {2}".format(key, - dict1[key], - dict2[key]) - if not equivalent: - return False, "['{0}']".format(key) + msg - return equivalent, msg - - -def comp_nums(num1, num2, tol=10e-8): - return abs(num1-num2) < tol - - -def comp_num_list(list1, list2, tol=10e-8): - for item1, item2 in zip(list1, list2): - if not comp_nums(item1, item2, tol): - return False - return True - - -def is_num_list(item): - try: - for thing in item: - if not isinstance(thing, Num): - raise TypeError - except TypeError: - return False - return True - - -def run_fig(fig): - renderer = PlotlyRenderer() - exporter = Exporter(renderer) - exporter.run(fig) - return renderer diff --git a/plotly/tests/test_optional/optional_utils.py b/plotly/tests/test_optional/optional_utils.py index 684e25faea4..74308de7f53 100644 --- a/plotly/tests/test_optional/optional_utils.py +++ b/plotly/tests/test_optional/optional_utils.py @@ -1,15 +1,18 @@ from __future__ import absolute_import -import matplotlib -# Force matplotlib to not use any Xwindows backend. -matplotlib.use('Agg') - import numpy as np -from plotly.matplotlylib import Exporter, PlotlyRenderer from plotly.tests.utils import is_num_list from plotly.utils import get_by_path, node_generator +# TODO: matplotlib-build-wip +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + import matplotlib + # Force matplotlib to not use any Xwindows backend. + matplotlib.use('Agg') + from plotly.matplotlylib import Exporter, PlotlyRenderer + def run_fig(fig): renderer = PlotlyRenderer() diff --git a/plotly/tests/test_optional/test_matplotlylib/test_annotations.py b/plotly/tests/test_optional/test_matplotlylib/test_annotations.py index a81703f31d8..d4987d01b70 100644 --- a/plotly/tests/test_optional/test_matplotlylib/test_annotations.py +++ b/plotly/tests/test_optional/test_matplotlylib/test_annotations.py @@ -1,15 +1,22 @@ from __future__ import absolute_import -import matplotlib -# Force matplotlib to not use any Xwindows backend. -matplotlib.use('Agg') -import matplotlib.pyplot as plt +from nose.plugins.attrib import attr -from plotly.tests.utils import compare_dict -from plotly.tests.test_optional.optional_utils import run_fig -from plotly.tests.test_optional.test_matplotlylib.data.annotations import * +# TODO: matplotlib-build-wip +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + import matplotlib + # Force matplotlib to not use any Xwindows backend. + matplotlib.use('Agg') + import matplotlib.pyplot as plt + from plotly.tests.utils import compare_dict + from plotly.tests.test_optional.optional_utils import run_fig + from plotly.tests.test_optional.test_matplotlylib.data.annotations import * + + +@attr('matplotlib') def test_annotations(): fig, ax = plt.subplots() ax.plot([1, 2, 3], 'b-') diff --git a/plotly/tests/test_optional/test_matplotlylib/test_axis_scales.py b/plotly/tests/test_optional/test_matplotlylib/test_axis_scales.py index 3fc0d0ed0c7..277b886d9fd 100644 --- a/plotly/tests/test_optional/test_matplotlylib/test_axis_scales.py +++ b/plotly/tests/test_optional/test_matplotlylib/test_axis_scales.py @@ -1,15 +1,22 @@ from __future__ import absolute_import -import matplotlib -# Force matplotlib to not use any Xwindows backend. -matplotlib.use('Agg') -import matplotlib.pyplot as plt +from nose.plugins.attrib import attr from plotly.tests.utils import compare_dict from plotly.tests.test_optional.optional_utils import run_fig from plotly.tests.test_optional.test_matplotlylib.data.axis_scales import * +# TODO: matplotlib-build-wip +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + import matplotlib + # Force matplotlib to not use any Xwindows backend. + matplotlib.use('Agg') + import matplotlib.pyplot as plt + + +@attr('matplotlib') def test_even_linear_scale(): fig, ax = plt.subplots() x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] diff --git a/plotly/tests/test_optional/test_matplotlylib/test_bars.py b/plotly/tests/test_optional/test_matplotlylib/test_bars.py index e6cff6cf518..feb439dd2c8 100644 --- a/plotly/tests/test_optional/test_matplotlylib/test_bars.py +++ b/plotly/tests/test_optional/test_matplotlylib/test_bars.py @@ -1,15 +1,22 @@ from __future__ import absolute_import -import matplotlib -# Force matplotlib to not use any Xwindows backend. -matplotlib.use('Agg') -import matplotlib.pyplot as plt +from nose.plugins.attrib import attr from plotly.tests.utils import compare_dict from plotly.tests.test_optional.optional_utils import run_fig from plotly.tests.test_optional.test_matplotlylib.data.bars import * +# TODO: matplotlib-build-wip +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + import matplotlib + # Force matplotlib to not use any Xwindows backend. + matplotlib.use('Agg') + import matplotlib.pyplot as plt + + +@attr('matplotlib') def test_vertical_bar(): fig, ax = plt.subplots() ax.bar(left=D['left'], height=D['height']) @@ -23,6 +30,7 @@ def test_vertical_bar(): assert equivalent, msg +@attr('matplotlib') def test_horizontal_bar(): fig, ax = plt.subplots() ax.barh(bottom=D['bottom'], width=D['width']) @@ -36,6 +44,7 @@ def test_horizontal_bar(): assert equivalent, msg +@attr('matplotlib') def test_h_and_v_bars(): fig, ax = plt.subplots() ax.bar(left=D['multi_left'], height=D['multi_height'], diff --git a/plotly/tests/test_optional/test_matplotlylib/test_data.py b/plotly/tests/test_optional/test_matplotlylib/test_data.py index 8662e5e10b1..33ad00543a3 100644 --- a/plotly/tests/test_optional/test_matplotlylib/test_data.py +++ b/plotly/tests/test_optional/test_matplotlylib/test_data.py @@ -1,14 +1,21 @@ from __future__ import absolute_import -import matplotlib -# Force matplotlib to not use any Xwindows backend. -matplotlib.use('Agg') -import matplotlib.pyplot as plt +from nose.plugins.attrib import attr from plotly.tests.test_optional.optional_utils import run_fig from plotly.tests.test_optional.test_matplotlylib.data.data import * +# TODO: matplotlib-build-wip +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + import matplotlib + # Force matplotlib to not use any Xwindows backend. + matplotlib.use('Agg') + import matplotlib.pyplot as plt + + +@attr('matplotlib') def test_line_data(): fig, ax = plt.subplots() ax.plot(D['x1'], D['y1']) @@ -21,6 +28,7 @@ def test_line_data(): renderer.plotly_fig['data'][0]['y']) + ' is not ' + str(D['y1']) +@attr('matplotlib') def test_lines_data(): fig, ax = plt.subplots() ax.plot(D['x1'], D['y1']) @@ -40,6 +48,7 @@ def test_lines_data(): renderer.plotly_fig['data'][0]['y']) + ' is not ' + str(D['y2']) +@attr('matplotlib') def test_bar_data(): fig, ax = plt.subplots() ax.bar(D['x1'], D['y1']) @@ -49,6 +58,7 @@ def test_bar_data(): renderer.plotly_fig['data'][0]['y']) + ' is not ' + str(D['y1']) +@attr('matplotlib') def test_bars_data(): fig, ax = plt.subplots() ax.bar(D['x1'], D['y1'], color='r') diff --git a/plotly/tests/test_optional/test_matplotlylib/test_date_times.py b/plotly/tests/test_optional/test_matplotlylib/test_date_times.py index 2f23cc97cdb..0c56efd5ad6 100644 --- a/plotly/tests/test_optional/test_matplotlylib/test_date_times.py +++ b/plotly/tests/test_optional/test_matplotlylib/test_date_times.py @@ -4,17 +4,25 @@ import random from unittest import TestCase -import matplotlib -# Force matplotlib to not use any Xwindows backend. -matplotlib.use('Agg') -from matplotlib.dates import date2num -import matplotlib.pyplot as plt import pandas as pd +from nose.plugins.attrib import attr import plotly.tools as tls +# TODO: matplotlib-build-wip +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + import matplotlib + # Force matplotlib to not use any Xwindows backend. + matplotlib.use('Agg') + from matplotlib.dates import date2num + import matplotlib.pyplot as plt + + +@attr('matplotlib') class TestDateTimes(TestCase): + def test_normal_mpl_dates(self): datetime_format = '%Y-%m-%d %H:%M:%S' y = [1, 2, 3, 4] diff --git a/plotly/tests/test_optional/test_matplotlylib/test_lines.py b/plotly/tests/test_optional/test_matplotlylib/test_lines.py index 2c12ae7d27e..9d1074bc571 100644 --- a/plotly/tests/test_optional/test_matplotlylib/test_lines.py +++ b/plotly/tests/test_optional/test_matplotlylib/test_lines.py @@ -1,15 +1,22 @@ from __future__ import absolute_import -import matplotlib -# Force matplotlib to not use any Xwindows backend. -matplotlib.use('Agg') -import matplotlib.pyplot as plt +from nose.plugins.attrib import attr from plotly.tests.utils import compare_dict from plotly.tests.test_optional.optional_utils import run_fig from plotly.tests.test_optional.test_matplotlylib.data.lines import * +# TODO: matplotlib-build-wip +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + import matplotlib + # Force matplotlib to not use any Xwindows backend. + matplotlib.use('Agg') + import matplotlib.pyplot as plt + + +@attr('matplotlib') def test_simple_line(): fig, ax = plt.subplots() ax.plot(D['x1'], D['y1'], label='simple') @@ -22,6 +29,7 @@ def test_simple_line(): assert equivalent, msg +@attr('matplotlib') def test_complicated_line(): fig, ax = plt.subplots() ax.plot(D['x1'], D['y1'], 'ro', markersize=10, alpha=.5, label='one') diff --git a/plotly/tests/test_optional/test_matplotlylib/test_scatter.py b/plotly/tests/test_optional/test_matplotlylib/test_scatter.py index 4bd0d8a2445..07fc276f5fb 100644 --- a/plotly/tests/test_optional/test_matplotlylib/test_scatter.py +++ b/plotly/tests/test_optional/test_matplotlylib/test_scatter.py @@ -1,15 +1,22 @@ from __future__ import absolute_import -import matplotlib -# Force matplotlib to not use any Xwindows backend. -matplotlib.use('Agg') -import matplotlib.pyplot as plt +from nose.plugins.attrib import attr from plotly.tests.utils import compare_dict from plotly.tests.test_optional.optional_utils import run_fig from plotly.tests.test_optional.test_matplotlylib.data.scatter import * +# TODO: matplotlib-build-wip +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + import matplotlib + # Force matplotlib to not use any Xwindows backend. + matplotlib.use('Agg') + import matplotlib.pyplot as plt + + +@attr('matplotlib') def test_simple_scatter(): fig, ax = plt.subplots() ax.scatter(D['x1'], D['y1']) @@ -23,6 +30,7 @@ def test_simple_scatter(): assert equivalent, msg +@attr('matplotlib') def test_double_scatter(): fig, ax = plt.subplots() ax.scatter(D['x1'], D['y1'], color='red', s=121, marker='^', alpha=0.5) diff --git a/plotly/tests/test_optional/test_matplotlylib/test_subplots.py b/plotly/tests/test_optional/test_matplotlylib/test_subplots.py index 2a26188e34f..725ca8aa78b 100644 --- a/plotly/tests/test_optional/test_matplotlylib/test_subplots.py +++ b/plotly/tests/test_optional/test_matplotlylib/test_subplots.py @@ -1,16 +1,23 @@ from __future__ import absolute_import -import matplotlib -# Force matplotlib to not use any Xwindows backend. -matplotlib.use('Agg') -from matplotlib.gridspec import GridSpec -import matplotlib.pyplot as plt +from nose.plugins.attrib import attr from plotly.tests.utils import compare_dict from plotly.tests.test_optional.optional_utils import run_fig from plotly.tests.test_optional.test_matplotlylib.data.subplots import * +# TODO: matplotlib-build-wip +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + import matplotlib + # Force matplotlib to not use any Xwindows backend. + matplotlib.use('Agg') + from matplotlib.gridspec import GridSpec + import matplotlib.pyplot as plt + + +@attr('matplotlib') def test_blank_subplots(): fig = plt.figure() gs = GridSpec(4, 6) diff --git a/plotly/tests/test_optional/test_plotly/test_plot_mpl.py b/plotly/tests/test_optional/test_plotly/test_plot_mpl.py index fc4878e91ea..e509d59d82a 100644 --- a/plotly/tests/test_optional/test_plotly/test_plot_mpl.py +++ b/plotly/tests/test_optional/test_plotly/test_plot_mpl.py @@ -7,11 +7,6 @@ """ from __future__ import absolute_import -import matplotlib - -# Force matplotlib to not use any Xwindows backend. -matplotlib.use('Agg') -import matplotlib.pyplot as plt from nose.plugins.attrib import attr from nose.tools import raises @@ -19,7 +14,17 @@ from plotly.plotly import plotly as py from unittest import TestCase +# TODO: matplotlib-build-wip +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + import matplotlib + + # Force matplotlib to not use any Xwindows backend. + matplotlib.use('Agg') + import matplotlib.pyplot as plt + +@attr('matplotlib') class PlotMPLTest(TestCase): def setUp(self): py.sign_in('PlotlyImageTest', '786r5mecv0', diff --git a/plotly/tests/test_optional/test_utils/test_utils.py b/plotly/tests/test_optional/test_utils/test_utils.py index 7d6e1a42eae..9cefd68ef35 100644 --- a/plotly/tests/test_optional/test_utils/test_utils.py +++ b/plotly/tests/test_optional/test_utils/test_utils.py @@ -10,16 +10,21 @@ from datetime import datetime as dt from unittest import TestCase -import matplotlib.pyplot as plt import numpy as np import pandas as pd -from pandas.util.testing import assert_series_equal import pytz +from nose.plugins.attrib import attr +from pandas.util.testing import assert_series_equal from plotly import utils from plotly.graph_objs import Scatter, Scatter3d, Figure, Data from plotly.grid_objs import Column -from plotly.matplotlylib import Exporter, PlotlyRenderer + +# TODO: matplotlib-build-wip +from plotly.tools import _matplotlylib_imported +if _matplotlylib_imported: + import matplotlib.pyplot as plt + from plotly.matplotlylib import Exporter, PlotlyRenderer class TestJSONEncoder(TestCase): @@ -253,6 +258,7 @@ def test_numpy_masked_json_encoding(): assert(j1 == '[1, 2, null]') +@attr('matplotlib') def test_masked_constants_example(): # example from: https://gist.github.com/tschaume/d123d56bf586276adb98 data = {