diff --git a/plotly/__init__.py b/plotly/__init__.py index 36b8131c039..0bd411480e6 100644 --- a/plotly/__init__.py +++ b/plotly/__init__.py @@ -28,5 +28,6 @@ from __future__ import absolute_import -from plotly import plotly, graph_objs, grid_objs, tools, utils, session, offline +from plotly import (plotly, graph_objs, grid_objs, tools, utils, session, + offline) from plotly.version import __version__ diff --git a/plotly/exceptions.py b/plotly/exceptions.py index ff25df04427..593e9923335 100644 --- a/plotly/exceptions.py +++ b/plotly/exceptions.py @@ -15,21 +15,14 @@ """ -import sys -import six +import json -if sys.version[:3] == '2.6': - import simplejson as json -else: - import json - -## Base Plotly Error ## +# Base Plotly Error class PlotlyError(Exception): pass - class InputError(PlotlyError): pass @@ -63,8 +56,7 @@ def __str__(self): return self.message -## Grid Errors ## - +# Grid Errors # COLUMN_NOT_YET_UPLOADED_MESSAGE = ( "Hm... it looks like your column '{column_name}' hasn't " "been uploaded to Plotly yet. You need to upload your " @@ -79,14 +71,14 @@ def __str__(self): "can't have duplicate column names. Rename " "the column \"{0}\" and try again." ) -## Would Cause Server Errors ## + +# Would Cause Server Errors class PlotlyEmptyDataError(PlotlyError): pass -## Graph Objects Errors ## - +# Graph Objects Errors class PlotlyGraphObjectError(PlotlyError): def __init__(self, message='', path=None, notes=None, plain_message=''): self.message = message @@ -202,8 +194,7 @@ def __init__(self, obj='', index='', **kwargs): **kwargs) -## Local Config Errors ## - +# Local Config Errors class PlotlyLocalError(PlotlyError): pass @@ -224,8 +215,7 @@ def __init__(self): super(PlotlyLocalCredentialsError, self).__init__(message) -## Server Errors ## - +# Server Errors class PlotlyServerError(PlotlyError): pass @@ -244,3 +234,20 @@ class PlotlyAccountError(PlotlyServerError): class PlotlyRateLimitError(PlotlyServerError): pass + + +class ClosedConnection(PlotlyConnectionError): + """Raised when the Plotly streaming server has disconnected.""" + def __init__(self, message, status_code=None): + self.message = "[Code: {}] {}".format(status_code, message) + self.status_code = status_code or None + super(ClosedConnection, self).__init__(self.message) + + +class TooManyConnectFailures(PlotlyConnectionError): + """Raised when too many unsuccessful (re)connects were attempted""" + message = "Connecting or reconnecting to stream failed too many times." + + def __init__(self, message=None): + message = message or self.message + super(TooManyConnectFailures, self).__init__(message) diff --git a/plotly/graph_objs/graph_objs.py b/plotly/graph_objs/graph_objs.py index 76fbd71027d..d4934948508 100644 --- a/plotly/graph_objs/graph_objs.py +++ b/plotly/graph_objs/graph_objs.py @@ -24,23 +24,19 @@ """ from __future__ import absolute_import +import copy +import sys import warnings +from collections import OrderedDict + import six + +from plotly import exceptions, utils from plotly.graph_objs import graph_objs_tools from plotly.graph_objs.graph_objs_tools import ( INFO, OBJ_MAP, NAME_TO_KEY, KEY_TO_NAME ) -from plotly import exceptions -from plotly import utils - -import copy -import sys -if sys.version[:3] == '2.6': - from ordereddict import OrderedDict -else: - from collections import OrderedDict - __all__ = None diff --git a/plotly/graph_objs/graph_objs_tools.py b/plotly/graph_objs/graph_objs_tools.py index e828df7fd5e..7a1ea8c1561 100644 --- a/plotly/graph_objs/graph_objs_tools.py +++ b/plotly/graph_objs/graph_objs_tools.py @@ -1,25 +1,14 @@ from __future__ import absolute_import -from plotly import utils -import textwrap + +import json import os -import sys -if sys.version[:3] == '2.6': - try: - from ordereddict import OrderedDict - import simplejson as json - except ImportError: - raise ImportError( - "Looks like you're running Python 2.6. Plotly expects newer " - "standard library versions of ordereddict and json. You can " - "simply upgrade with these 'extras' with the following terminal " - "command:\npip install 'plotly[PY2.6]'" - ) -else: - from collections import OrderedDict - import json +import textwrap +from collections import OrderedDict +from pkg_resources import resource_string + import six -from pkg_resources import resource_string +from plotly import utils # Define graph reference loader diff --git a/plotly/grid_objs/__init__.py b/plotly/grid_objs/__init__.py index e4f0f85be34..bddd0a36482 100644 --- a/plotly/grid_objs/__init__.py +++ b/plotly/grid_objs/__init__.py @@ -3,6 +3,6 @@ ========= """ +from __future__ import absolute_import - -from . grid_objs import Grid, Column +from plotly.grid_objs.grid_objs import Grid, Column diff --git a/plotly/grid_objs/grid_objs.py b/plotly/grid_objs/grid_objs.py index 8dc8faaab90..743ead1bff7 100644 --- a/plotly/grid_objs/grid_objs.py +++ b/plotly/grid_objs/grid_objs.py @@ -5,15 +5,10 @@ """ from __future__ import absolute_import -import sys +import json from collections import MutableSequence -from plotly import exceptions -from plotly import utils -if sys.version[:3] == '2.6': - import simplejson as json -else: - import json +from plotly import exceptions, utils __all__ = None diff --git a/plotly/matplotlylib/__init__.py b/plotly/matplotlylib/__init__.py index 8d0825aca63..7a5b7b83169 100644 --- a/plotly/matplotlylib/__init__.py +++ b/plotly/matplotlylib/__init__.py @@ -9,5 +9,7 @@ 'tools' module or 'plotly' package. """ -from . renderer import PlotlyRenderer -from . mplexporter import Exporter \ No newline at end of file +from __future__ import absolute_import + +from plotly.matplotlylib.renderer import PlotlyRenderer +from plotly.matplotlylib.mplexporter import Exporter diff --git a/plotly/matplotlylib/mpltools.py b/plotly/matplotlylib/mpltools.py index 0082539f718..a29c302edb8 100644 --- a/plotly/matplotlylib/mpltools.py +++ b/plotly/matplotlylib/mpltools.py @@ -4,9 +4,9 @@ A module for converting from mpl language to plotly language. """ - import math import warnings + import matplotlib.dates import pytz diff --git a/plotly/matplotlylib/renderer.py b/plotly/matplotlylib/renderer.py index 3eb7494ecba..fde96dfcb31 100644 --- a/plotly/matplotlylib/renderer.py +++ b/plotly/matplotlylib/renderer.py @@ -10,9 +10,9 @@ import warnings -from . mplexporter import Renderer -from . import mpltools import plotly.graph_objs as go +from plotly.matplotlylib.mplexporter import Renderer +from plotly.matplotlylib import mpltools # Warning format diff --git a/plotly/offline/offline.py b/plotly/offline/offline.py index cd137d56f0a..ba43d65ec9f 100644 --- a/plotly/offline/offline.py +++ b/plotly/offline/offline.py @@ -5,15 +5,14 @@ """ from __future__ import absolute_import -import uuid import json import os +import uuid + import requests -from plotly import utils -from plotly import tools +from plotly import session, tools, utils from plotly.exceptions import PlotlyError -from plotly import session PLOTLY_OFFLINE_DIRECTORY = plotlyjs_path = os.path.expanduser( os.path.join(*'~/.plotly/plotlyjs'.split('/'))) diff --git a/plotly/plotly/__init__.py b/plotly/plotly/__init__.py index d6670e25c34..b252967935f 100644 --- a/plotly/plotly/__init__.py +++ b/plotly/plotly/__init__.py @@ -18,6 +18,7 @@ plot_mpl, get_figure, Stream, + StreamWriter, image, grid_ops, meta_ops, diff --git a/plotly/plotly/plotly.py b/plotly/plotly/plotly.py index 8b34a787697..698f326887b 100644 --- a/plotly/plotly/plotly.py +++ b/plotly/plotly/plotly.py @@ -16,33 +16,28 @@ """ from __future__ import absolute_import -import sys -import warnings +import base64 import copy +import json +import socket import os -import six -import base64 -import requests - -if sys.version[:1] == '2': - from urlparse import urlparse -else: - from urllib.parse import urlparse +import threading +import time +import warnings +from collections import deque -if sys.version[:3] == '2.6': - import simplejson as json -else: - import json +import requests +import six +import six.moves +import trollius +from trollius import From, Return, TimeoutError +from plotly import exceptions, tools, utils, version from plotly.plotly import chunked_requests -from plotly import utils -from plotly import tools -from plotly import exceptions -from plotly import version from plotly.session import (sign_in, update_session_plot_options, get_session_plot_options, get_session_credentials, get_session_config) - +from plotly.utils import HttpResponseParser, DisconnectThread __all__ = None @@ -366,6 +361,295 @@ def get_figure(file_owner_or_url, file_id=None, raw=False): "There was an error retrieving this file") +class StreamWriter(object): + """ + Class to help stream to Plotly's streaming server. + + """ + linear_back_off_rate = 0.250 # additional seconds per retry + linear_wait_max = 16 # seconds + + exponential_back_off_base = 5 # base for exponentiation + exponential_wait_max = 320 # seconds + + eol = '\r\n' # end of line character for our http communication + + def __init__(self, token, ignore_status_codes=(None, 200), + ignore_errors=(), queue_length=500, initial_write_timeout=4): + """ + Initialize a StreamWriter which can write to Plotly's streaming server. + + :param (str) token: The Plotly streaming token which links a trace to + this data stream. *Not* your Plotly api_key. + + :param ignore_status_codes: Http status codes to ignore from server and + reconnect on. + + :param (int) queue_length: The maximum number of messages to store if + we're waiting to communicate with server. + + :param (int) initial_write_timeout: Seconds to wait for a response from + the streaming server after the initial http request is sent. + + :param ignore_errors: Exception classes to ignore and reconnect on. + Useful if you want quietly reconnect on network hiccups. + + """ + self.token = token + self.ignore_status_codes = ignore_status_codes + self.ignore_errors = ignore_errors + self.queue_length = queue_length + self.initial_write_timeout = initial_write_timeout + + self._queue = deque(maxlen=self.queue_length) # prevent memory leaks + self._last_beat = None + + self._connect_errors = 0 + self._last_connect_error = time.time() + self._disconnections = 0 + self._last_disconnection = time.time() + + self._thread = None + self._reader = None + self._writer = None + + self._error = None + self._response = None + + # hold reference to germain credentials/config at instantiation time. + self.host = get_config()['plotly_streaming_domain'] + self.port = 80 + + self._headers = {'Plotly-Streamtoken': self.token, 'Host': self.host, + 'Transfer-Encoding': 'chunked', + 'Content-Type': 'text/plain'} + + def _reset(self): + """Prep some attributes to reconnect.""" + self._response = None + self._error = None + self._last_beat = None + self._reader = None + self._writer = None + + def _back_off_linearly(self): + """Back off linearly if connect exceptions are thrown in the thread.""" + now = time.time() + if now - self._last_connect_error > self.linear_wait_max * 2: + self._connect_errors = 0 + self._last_connect_error = now + + self._connect_errors += 1 + wait_time = self._connect_errors * self.linear_back_off_rate + if wait_time > self.linear_wait_max: + raise exceptions.TooManyConnectFailures + else: + time.sleep(wait_time) + + def _back_off_exponentially(self): + """Back off exponentially if peer keeps disconnecting.""" + now = time.time() + if now - self._last_disconnection > self.exponential_wait_max * 2: + self._disconnections = 0 + self._last_disconnection = now + + self._disconnections += 1 + wait_time = self.exponential_back_off_base ** self._disconnections + if wait_time > self.exponential_wait_max: + raise exceptions.TooManyConnectFailures + else: + time.sleep(wait_time) + + def _raise_for_response(self): + """If we got a response, the server disconnected. Possibly raise.""" + if self._response is None: + return + + try: + response = self.response + message = response.read() + status = response.status + except (AttributeError, six.moves.http_client.BadStatusLine): + message = '' + status = None + + if status not in self.ignore_status_codes: + raise exceptions.ClosedConnection(message, status_code=status) + + # if we didn't raise here, we need to at least back off + if status >= 500: + self._back_off_linearly() # it's the server's fault. + else: + self._back_off_exponentially() # it's the client's fault. + + def _raise_for_error(self): + """If there was an error during reading/writing, possibly raise.""" + if self._error is None: + return + + if not isinstance(self._error, self.ignore_errors): + raise self._error + + # if we didn't raise here, we need to at least back off + if isinstance(self._error, socket.error): + self._back_off_linearly() + + # TODO: do we need to dive into the socket error numbers here? + + def _check_pulse(self): + """Streams get shut down after 60 seconds of inactivity.""" + self._last_beat = self._last_beat or time.time() + now = time.time() + if now - self._last_beat > 30: + self._last_beat = now + if not self._queue: + self.write('') + + def _initial_write(self): + """Write our request-line and readers with a blank body.""" + self._writer.write('POST / HTTP/1.1') + self._writer.write(self.eol) + for header, header_value in self._headers.items(): + self._writer.write('{}: {}'.format(header, header_value)) + self._writer.write(self.eol) + self._writer.write(self.eol) + + def _write(self): + """Check the queue, if it's not empty, write a chunk!""" + if self._queue: + self._chunk = self._queue.pop() + hex_len = format(len(self._chunk), 'x') + self._writer.write() + message = '{}\r\n{}\r\n'.format(hex_len, self._chunk) + self._writer.write(message.encode('utf-8')) + + @trollius.coroutine + def _read(self, timeout=0.01): + """ + Read the whole buffer or return None if nothing's there. + + :return: (str|None) + + """ + try: + data = yield From(trollius.wait_for(self._reader.read(), + timeout=timeout)) + except TimeoutError: + data = None + + # This is how we return from coroutines with trollius + raise Return(data) + + @trollius.coroutine + def _read_write(self): + """ + Entry point into coroutine functionality. + + Creates a reader and a writer by opening a connection to Plotly's + streaming server. Then, it loops forever! + + """ + try: + # open up a connection and get our StreamReader/StreamWriter + current_thread = threading.current_thread() + self._reader, self._writer = yield From(trollius.wait_for( + trollius.open_connection(self.host, self.port), timeout=60 + )) + + # wait for an initial failure response, e.g., bad headers + self._initial_write() + self._response = yield From(self._read(self.initial_write_timeout)) + + # read/write until server responds or thread is disconnected. + while self._response is None and current_thread.connected: + self._check_pulse() + self._response = yield From(self._read()) # usually just None. + self._write() + + except Exception as e: + self._error = e + finally: + if self._writer: + self._writer.close() + + def _thread_func(self, loop): + """ + StreamWriters have threads that loop coroutines forever. + + :param loop: From `trollius.get_event_loop()` + + """ + trollius.set_event_loop(loop) + loop.run_until_complete(self._read_write()) + + @property + def connected(self): + """Returns state of the StreamWriter's thread.""" + return self._thread and self._thread.isAlive() + + @property + def response(self): + """Return a response object parsed from server string response.""" + if self._response is None: + return None + return HttpResponseParser(self._response).get_response() + + def open(self): + """ + Standard `open` API. Strictly unnecessary as it opens on `write`. + + If not already opened, start a new daemon thread to consume the buffer. + + """ + if self.connected: + return + + # if we've previously hit a failure, we should let the user know + self._raise_for_response() + self._raise_for_error() + + # reset our error, response, pulse information, etc. + self._reset() + + # start up a new daemon thread + loop = trollius.get_event_loop() + self._thread = DisconnectThread(target=self._thread_func, args=(loop,)) + self._thread.setDaemon(True) + self._thread.start() + + def write(self, chunk): + """ + Standard `write` API. + + Reopens connection if closed and appends chunk to buffer. + + If chunk isn't a str|unicode, `json.dumps` is called with chunk. + + :param (str|unicode|dict) chunk: The data to be queued to send. + + """ + if not self.connected: + self.open() + + if not isinstance(chunk, six.string_types): + chunk = json.dumps(chunk, cls=utils.PlotlyJSONEncoder) + + self._queue.appendleft(chunk + '\n') # needs at least 1 trailing '\n' + + def close(self): + """ + Standard `close` API. + + Ensures thread is disconnected. + + """ + if not self.connected: + return + + self._thread.disconnect() # lets thread know to stop communicating + self._thread = None + + @utils.template_doc(**tools.get_config_file()) class Stream: """ @@ -1158,7 +1442,7 @@ def parse_grid_id_args(cls, grid, grid_url): else: supplied_arg_name = supplied_arg_names.pop() if supplied_arg_name == 'grid_url': - path = urlparse(grid_url).path + path = six.moves.urllib.parse.urlparse(grid_url).path file_owner, file_id = path.replace("/~", "").split('/')[0:2] return '{0}:{1}'.format(file_owner, file_id) else: diff --git a/plotly/session.py b/plotly/session.py index dea8b566b53..3c165c6ea90 100644 --- a/plotly/session.py +++ b/plotly/session.py @@ -5,10 +5,13 @@ which user they're signed in as, and plotting defaults. """ +from __future__ import absolute_import import copy + import six -from . import exceptions + +from plotly import exceptions _session = { 'credentials': {}, diff --git a/plotly/tests/test_core/test_get_figure/__init__.py b/plotly/tests/test_core/test_get_figure/__init__.py index 73f1ee4bb1e..e69de29bb2d 100644 --- a/plotly/tests/test_core/test_get_figure/__init__.py +++ b/plotly/tests/test_core/test_get_figure/__init__.py @@ -1,6 +0,0 @@ -def setup_package(): - pass - - -def teardown_package(): - pass \ No newline at end of file diff --git a/plotly/tests/test_core/test_get_figure/test_get_figure.py b/plotly/tests/test_core/test_get_figure/test_get_figure.py index 85a92d264a4..23e393450dc 100644 --- a/plotly/tests/test_core/test_get_figure/test_get_figure.py +++ b/plotly/tests/test_core/test_get_figure/test_get_figure.py @@ -5,16 +5,16 @@ A module intended for use with Nose. """ -from plotly.graph_objs import graph_objs -from plotly.plotly import plotly as py -from plotly import exceptions -from nose.tools import raises -import six +from __future__ import absolute_import -from unittest import TestCase +from unittest import TestCase, skipIf -version = six.sys.version_info[:2] # need this for conditional testing +from nose.tools import raises +import six +from plotly import exceptions +from plotly.graph_objs import graph_objs +from plotly.plotly import plotly as py # username for tests: 'plotlyimagetest' # api_key for account: '786r5mecv0' @@ -53,8 +53,9 @@ def compare_with_raw(obj, raw_obj, parents=None): for entry, entry_raw in zip(obj, raw_obj): if isinstance(entry, (dict, list)): try: - coll_name = graph_objs.NAME_TO_KEY[entry.__class__ - .__name__] + coll_name = ( + graph_objs.NAME_TO_KEY[entry.__class__.__name__] + ) except KeyError: coll_name = entry.__class__.__name__ if parents is None: @@ -163,7 +164,7 @@ def test_all(): ak = '786r5mecv0' run_test = False end_file = 2 - polar_plots = [], #[6, 7, 8] + polar_plots = [], # [6, 7, 8] skip = list(range(0)) if run_test: py.sign_in(un, ak) @@ -198,18 +199,12 @@ def test_all(): class TestBytesVStrings(TestCase): - # unittest `skipIf` not supported in 2.6 - if version < (2, 7) or (2, 7) < version < (3, 3): - pass - else: - from unittest import skipIf - - @skipIf(not six.PY3, 'Decoding and missing escapes only seen in PY3') - def test_proper_escaping(self): - un = 'PlotlyImageTest' - ak = '786r5mecv0' - url = "https://plot.ly/~PlotlyImageTest/91/" - py.sign_in(un, ak) - print("getting: https://plot.ly/~PlotlyImageTest/91/") - print("###########################################\n\n") - fig = py.get_figure(url) + @skipIf(not six.PY3, 'Decoding and missing escapes only seen in PY3') + def test_proper_escaping(self): + un = 'PlotlyImageTest' + ak = '786r5mecv0' + url = "https://plot.ly/~PlotlyImageTest/91/" + py.sign_in(un, ak) + print("getting: https://plot.ly/~PlotlyImageTest/91/") + print("###########################################\n\n") + fig = py.get_figure(url) diff --git a/plotly/tests/test_core/test_get_requests/__init__.py b/plotly/tests/test_core/test_get_requests/__init__.py index 73f1ee4bb1e..e69de29bb2d 100644 --- a/plotly/tests/test_core/test_get_requests/__init__.py +++ b/plotly/tests/test_core/test_get_requests/__init__.py @@ -1,6 +0,0 @@ -def setup_package(): - pass - - -def teardown_package(): - pass \ No newline at end of file diff --git a/plotly/tests/test_core/test_get_requests/test_get_requests.py b/plotly/tests/test_core/test_get_requests/test_get_requests.py index 473fcd15ceb..438bd42ed5d 100644 --- a/plotly/tests/test_core/test_get_requests/test_get_requests.py +++ b/plotly/tests/test_core/test_get_requests/test_get_requests.py @@ -5,16 +5,12 @@ A module intended for use with Nose. """ - -import requests import copy +import json +import requests + import six -import sys -if sys.version[:3] == '2.6': - import simplejson as json -else: - import json default_headers = {'plotly-username': '', 'plotly-apikey': '', @@ -151,4 +147,3 @@ def test_valid_request(): # if figure['data'][0]['x'] != [u'1', u'2', u'3']: # print('ERROR') # return res - diff --git a/plotly/tests/test_core/test_graph_objs/__init__.py b/plotly/tests/test_core/test_graph_objs/__init__.py index d18b2e7d500..1118eb01e82 100644 --- a/plotly/tests/test_core/test_graph_objs/__init__.py +++ b/plotly/tests/test_core/test_graph_objs/__init__.py @@ -1,7 +1,5 @@ -def setup_package(): - import warnings - warnings.filterwarnings('ignore') +import warnings -def teardown_package(): - pass +def setup_package(): + warnings.filterwarnings('ignore') diff --git a/plotly/tests/test_core/test_graph_objs/nose_tools.py b/plotly/tests/test_core/test_graph_objs/nose_tools.py index 8cc5cefb07f..00f39e0fbd9 100644 --- a/plotly/tests/test_core/test_graph_objs/nose_tools.py +++ b/plotly/tests/test_core/test_graph_objs/nose_tools.py @@ -1,10 +1,12 @@ 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 -from numbers import Number as Num def compare_dict(dict1, dict2, equivalent=True, msg='', tol=10e-8): diff --git a/plotly/tests/test_core/test_graph_objs/test_annotations.py b/plotly/tests/test_core/test_graph_objs/test_annotations.py index 40f289c38da..000f5ec478d 100644 --- a/plotly/tests/test_core/test_graph_objs/test_annotations.py +++ b/plotly/tests/test_core/test_graph_objs/test_annotations.py @@ -8,12 +8,11 @@ from __future__ import absolute_import from nose.tools import raises -from plotly.graph_objs import * -from plotly.exceptions import (PlotlyError, - PlotlyDictKeyError, - PlotlyDictValueError, - PlotlyDataTypeError, - PlotlyListEntryError) + +from plotly.exceptions import (PlotlyError, PlotlyDictKeyError, + PlotlyDictValueError, PlotlyListEntryError) +from plotly.graph_objs import Annotation, Annotations, Data, Figure, Layout + def setup(): @@ -69,7 +68,7 @@ def test_validate(): annotations.validate() annotations += [{'text': 'some text'}] annotations.validate() - annotations += [{},{},{}] + annotations += [{}, {}, {}] annotations.validate() @@ -78,4 +77,3 @@ def test_validate_error(): annotations = Annotations() annotations.append({'not-a-key': 'anything'}) annotations.validate() - diff --git a/plotly/tests/test_core/test_graph_objs/test_append_trace.py b/plotly/tests/test_core/test_graph_objs/test_append_trace.py index 0ca385532f3..0690ce39c08 100644 --- a/plotly/tests/test_core/test_graph_objs/test_append_trace.py +++ b/plotly/tests/test_core/test_graph_objs/test_append_trace.py @@ -1,39 +1,39 @@ -import plotly -from plotly.graph_objs import * -import plotly.tools as tls +from __future__ import absolute_import + from nose.tools import raises +from plotly.graph_objs import (Data, Figure, Layout, Scatter, Scatter3d, Scene, + XAxis, YAxis) +import plotly.tools as tls + @raises(Exception) def test_print_grid_before_make_subplots(): + fig = Figure() fig.print_grid() + @raises(Exception) def test_append_trace_before_make_subplots(): - trace = Scatter( - x=[1,2,3], - y=[2,3,4] - ) + trace = Scatter(x=[1, 2, 3], y=[2, 3, 4]) + fig = Figure() fig.append_trace(trace, 2, 2) + @raises(Exception) def test_append_trace_row_out_of_range(): - trace = Scatter( - x=[1,2,3], - y=[2,3,4] - ) + trace = Scatter(x=[1, 2, 3], y=[2, 3, 4]) fig = tls.make_subplots(rows=2, cols=3) fig.append_trace(trace, 10, 2) + @raises(Exception) def test_append_trace_col_out_of_range(): - trace = Scatter( - x=[1,2,3], - y=[2,3,4] - ) + trace = Scatter(x=[1, 2, 3], y=[2, 3, 4]) fig = tls.make_subplots(rows=2, cols=3) fig.append_trace(trace, 2, 0) + def test_append_scatter(): expected = Figure( data=Data([ @@ -96,34 +96,28 @@ def test_append_scatter(): ) ) - trace = Scatter( - x=[1,2,3], - y=[2,3,4] - ) + trace = Scatter(x=[1, 2, 3], y=[2, 3, 4]) fig = tls.make_subplots(rows=2, cols=3) fig.append_trace(trace, 2, 2) assert fig == expected + @raises(Exception) def test_append_scatter_after_deleting_xaxis(): - trace = Scatter( - x=[1,2,3], - y=[2,3,4] - ) + trace = Scatter(x=[1, 2, 3], y=[2, 3, 4]) fig = tls.make_subplots(rows=2, cols=3) fig['layout'].pop('xaxis5', None) fig.append_trace(trace, 2, 2) + @raises(Exception) def test_append_scatter_after_deleting_yaxis(): - trace = Scatter( - x=[1,2,3], - y=[2,3,4] - ) + trace = Scatter(x=[1, 2, 3], y=[2, 3, 4]) fig = tls.make_subplots(rows=2, cols=3) fig['layout'].pop('yaxis5', None) fig.append_trace(trace, 2, 2) + def test_append_scatter3d(): expected = Figure( data=Data([ @@ -153,24 +147,17 @@ def test_append_scatter3d(): fig = tls.make_subplots(rows=2, cols=1, specs=[[{'is_3d': True}], [{'is_3d': True}]]) - trace = Scatter3d( - x=[1,2,3], - y=[2,3,4], - z=[1,2,3] - ) + trace = Scatter3d(x=[1, 2, 3], y=[2, 3, 4], z=[1, 2, 3]) fig.append_trace(trace, 1, 1) fig.append_trace(trace, 2, 1) assert fig == expected + @raises(Exception) def test_append_scatter3d_after_deleting_scene(): fig = tls.make_subplots(rows=2, cols=1, specs=[[{'is_3d': True}], [{'is_3d': True}]]) - trace = Scatter3d( - x=[1,2,3], - y=[2,3,4], - z=[1,2,3] - ) + trace = Scatter3d(x=[1, 2, 3], y=[2, 3, 4], z=[1, 2, 3]) fig['layout'].pop('scene1', None) fig.append_trace(trace, 1, 1) diff --git a/plotly/tests/test_core/test_graph_objs/test_consistency.py b/plotly/tests/test_core/test_graph_objs/test_consistency.py index bc38f1e06bc..51e32d97a3f 100644 --- a/plotly/tests/test_core/test_graph_objs/test_consistency.py +++ b/plotly/tests/test_core/test_graph_objs/test_consistency.py @@ -6,6 +6,8 @@ are properly defined in both graph_objs.py and included in the mapping dicts. """ +from __future__ import absolute_import + from plotly.graph_objs import graph_objs diff --git a/plotly/tests/test_core/test_graph_objs/test_data.py b/plotly/tests/test_core/test_graph_objs/test_data.py index e8dd4b78819..6fd262505c9 100644 --- a/plotly/tests/test_core/test_graph_objs/test_data.py +++ b/plotly/tests/test_core/test_graph_objs/test_data.py @@ -8,12 +8,11 @@ from __future__ import absolute_import from nose.tools import raises -from plotly.graph_objs import * -from plotly.exceptions import (PlotlyError, - PlotlyDictKeyError, - PlotlyDictValueError, - PlotlyDataTypeError, + +from plotly.exceptions import (PlotlyError, PlotlyDictKeyError, + PlotlyDictValueError, PlotlyDataTypeError, PlotlyListEntryError) +from plotly.graph_objs import Annotations, Data, Figure, Layout def setup(): @@ -78,7 +77,7 @@ def test_validate(): data.validate() data += [{'type': 'scatter'}] data.validate() - data += [{},{},{}] + data += [{}, {}, {}] data.validate() @@ -87,4 +86,3 @@ def test_validate_error(): data = Data() data.append({'not-a-key': 'anything'}) data.validate() - diff --git a/plotly/tests/test_core/test_graph_objs/test_error_bars.py b/plotly/tests/test_core/test_graph_objs/test_error_bars.py index 3fa68e60395..15740ece4ab 100644 --- a/plotly/tests/test_core/test_graph_objs/test_error_bars.py +++ b/plotly/tests/test_core/test_graph_objs/test_error_bars.py @@ -8,11 +8,8 @@ from __future__ import absolute_import from nose.tools import raises -from plotly.graph_objs import * -from plotly.exceptions import (PlotlyDictKeyError, - PlotlyDictValueError, - PlotlyDataTypeError, - PlotlyListEntryError) +from plotly.graph_objs import ErrorX, ErrorY +from plotly.exceptions import PlotlyDictKeyError def test_instantiate_error_x(): diff --git a/plotly/tests/test_core/test_graph_objs/test_get_data.py b/plotly/tests/test_core/test_graph_objs/test_get_data.py index 8fbd0672418..981ec0a9063 100644 --- a/plotly/tests/test_core/test_graph_objs/test_get_data.py +++ b/plotly/tests/test_core/test_graph_objs/test_get_data.py @@ -2,7 +2,8 @@ from unittest import TestCase -from plotly.graph_objs import * +from plotly.graph_objs import (Data, Figure, Layout, Line, Margin, Marker, + Scatter, XAxis, YAxis) class TestGetData(TestCase): diff --git a/plotly/tests/test_core/test_graph_objs/test_get_ordered.py b/plotly/tests/test_core/test_graph_objs/test_get_ordered.py index bdad47644d8..328f0b0bc3a 100644 --- a/plotly/tests/test_core/test_graph_objs/test_get_ordered.py +++ b/plotly/tests/test_core/test_graph_objs/test_get_ordered.py @@ -1,11 +1,9 @@ from __future__ import absolute_import -try: - from collections import OrderedDict -except ImportError: - from ordereddict import OrderedDict +from collections import OrderedDict -from plotly.graph_objs import * +from plotly.graph_objs import (Data, Figure, Layout, Line, Margin, Marker, + Scatter, XAxis, YAxis) def test_get_ordered(): fig = Figure( @@ -26,11 +24,13 @@ def test_get_ordered(): ) ), Scatter( - x=[39317, 37236, 35650, 30066, 29570, 27159, 23557, 21046, 18007], + x=[39317, 37236, 35650, 30066, 29570, 27159, 23557, 21046, + 18007], y=[33, 20, 13, 19, 27, 19, 49, 44, 38], mode='markers', name='Europe', - text=['Germany', 'Britain', 'France', 'Spain', 'Italy', 'Czech Rep.', 'Greece', 'Poland'], + text=['Germany', 'Britain', 'France', 'Spain', 'Italy', + 'Czech Rep.', 'Greece', 'Poland'], marker=Marker( color='rgb(255, 217, 102)', size=12, @@ -45,7 +45,8 @@ def test_get_ordered(): y=[23, 42, 54, 89, 14, 99, 93, 70], mode='markers', name='Asia/Pacific', - text=['Australia', 'Japan', 'South Korea', 'Malaysia', 'China', 'Indonesia', 'Philippines', 'India'], + text=['Australia', 'Japan', 'South Korea', 'Malaysia', 'China', + 'Indonesia', 'Philippines', 'India'], marker=Marker( color='rgb(234, 153, 153)', size=12, @@ -60,7 +61,8 @@ def test_get_ordered(): y=[43, 47, 56, 80, 86, 93, 80], mode='markers', name='Latin America', - text=['Chile', 'Argentina', 'Mexico', 'Venezuela', 'Venezuela', 'El Salvador', 'Bolivia'], + text=['Chile', 'Argentina', 'Mexico', 'Venezuela', 'Venezuela', + 'El Salvador', 'Bolivia'], marker=Marker( color='rgb(142, 124, 195)', size=12, @@ -94,5 +96,79 @@ def test_get_ordered(): ) ) ordered_fig = fig.get_ordered() - comp_fig = OrderedDict([('data', [OrderedDict([('x', [52698, 43117]), ('y', [53, 31]), ('mode', 'markers'), ('name', 'North America'), ('text', ['United States', 'Canada']), ('marker', OrderedDict([('color', 'rgb(164, 194, 244)'), ('size', 12), ('line', OrderedDict([('color', 'white'), ('width', 0.5)]))])), ('type', 'scatter')]), OrderedDict([('x', [39317, 37236, 35650, 30066, 29570, 27159, 23557, 21046, 18007]), ('y', [33, 20, 13, 19, 27, 19, 49, 44, 38]), ('mode', 'markers'), ('name', 'Europe'), ('text', ['Germany', 'Britain', 'France', 'Spain', 'Italy', 'Czech Rep.', 'Greece', 'Poland']), ('marker', OrderedDict([('color', 'rgb(255, 217, 102)'), ('size', 12), ('line', OrderedDict([('color', 'white'), ('width', 0.5)]))])), ('type', 'scatter')]), OrderedDict([('x', [42952, 37037, 33106, 17478, 9813, 5253, 4692, 3899]), ('y', [23, 42, 54, 89, 14, 99, 93, 70]), ('mode', 'markers'), ('name', 'Asia/Pacific'), ('text', ['Australia', 'Japan', 'South Korea', 'Malaysia', 'China', 'Indonesia', 'Philippines', 'India']), ('marker', OrderedDict([('color', 'rgb(234, 153, 153)'), ('size', 12), ('line', OrderedDict([('color', 'white'), ('width', 0.5)]))])), ('type', 'scatter')]), OrderedDict([('x', [19097, 18601, 15595, 13546, 12026, 7434, 5419]), ('y', [43, 47, 56, 80, 86, 93, 80]), ('mode', 'markers'), ('name', 'Latin America'), ('text', ['Chile', 'Argentina', 'Mexico', 'Venezuela', 'Venezuela', 'El Salvador', 'Bolivia']), ('marker', OrderedDict([('color', 'rgb(142, 124, 195)'), ('size', 12), ('line', OrderedDict([('color', 'white'), ('width', 0.5)]))])), ('type', 'scatter')])]), ('layout', OrderedDict([('title', 'Quarter 1 Growth'), ('autosize', False), ('width', 500), ('height', 500), ('xaxis', OrderedDict([('title', 'GDP per Capita'), ('showgrid', False), ('zeroline', False)])), ('yaxis', OrderedDict([('title', 'Percent'), ('showline', False)])), ('margin', OrderedDict([('l', 65), ('r', 50), ('b', 65), ('t', 90)]))]))]) + comp_fig = OrderedDict( + [('data', [ + OrderedDict([ + ('x', [52698, 43117]), + ('y', [53, 31]), + ('mode', 'markers'), + ('name', 'North America'), + ('text', ['United States', 'Canada']), + ('marker', OrderedDict([ + ('color', 'rgb(164, 194, 244)'), + ('size', 12), + ('line', OrderedDict([ + ('color', 'white'), + ('width', 0.5)]))])), + ('type', 'scatter')]), + OrderedDict([ + ('x', [39317, 37236, 35650, 30066, 29570, 27159, 23557, 21046, + 18007]), + ('y', [33, 20, 13, 19, 27, 19, 49, 44, 38]), + ('mode', 'markers'), + ('name', 'Europe'), + ('text', ['Germany', 'Britain', 'France', 'Spain', 'Italy', + 'Czech Rep.', 'Greece', 'Poland']), + ('marker', OrderedDict([ + ('color', 'rgb(255, 217, 102)'), + ('size', 12), + ('line', OrderedDict([ + ('color', 'white'), + ('width', 0.5)]))])), + ('type', 'scatter')]), + OrderedDict([ + ('x', [42952, 37037, 33106, 17478, 9813, 5253, 4692, 3899]), + ('y', [23, 42, 54, 89, 14, 99, 93, 70]), + ('mode', 'markers'), + ('name', 'Asia/Pacific'), + ('text', ['Australia', 'Japan', 'South Korea', 'Malaysia', + 'China', 'Indonesia', 'Philippines', 'India']), + ('marker', OrderedDict([ + ('color', 'rgb(234, 153, 153)'), + ('size', 12), + ('line', OrderedDict([ + ('color', 'white'), + ('width', 0.5)]))])), + ('type', 'scatter')]), + OrderedDict([ + ('x', [19097, 18601, 15595, 13546, 12026, 7434, 5419]), + ('y', [43, 47, 56, 80, 86, 93, 80]), + ('mode', 'markers'), + ('name', 'Latin America'), + ('text', ['Chile', 'Argentina', 'Mexico', 'Venezuela', + 'Venezuela', 'El Salvador', 'Bolivia']), + ('marker', OrderedDict([ + ('color', 'rgb(142, 124, 195)'), + ('size', 12), + ('line', OrderedDict([ + ('color', 'white'), + ('width', 0.5)]))])), + ('type', 'scatter')])]), + ('layout', OrderedDict([ + ('title', 'Quarter 1 Growth'), + ('autosize', False), + ('width', 500), + ('height', 500), + ('xaxis', OrderedDict([ + ('title', 'GDP per Capita'), + ('showgrid', False), + ('zeroline', False)])), + ('yaxis', OrderedDict([ + ('title', 'Percent'), + ('showline', False)])), + ('margin', OrderedDict([ + ('l', 65), + ('r', 50), + ('b', 65), + ('t', 90)]))]))]) assert ordered_fig == comp_fig diff --git a/plotly/tests/test_core/test_graph_objs/test_graph_objs_tools.py b/plotly/tests/test_core/test_graph_objs/test_graph_objs_tools.py index 98a57aeccdb..fb16a0d7bf7 100644 --- a/plotly/tests/test_core/test_graph_objs/test_graph_objs_tools.py +++ b/plotly/tests/test_core/test_graph_objs/test_graph_objs_tools.py @@ -2,11 +2,6 @@ from unittest import TestCase -try: - from collections import OrderedDict -except ImportError: - from ordereddict import OrderedDict - from plotly.graph_objs.graph_objs_tools import value_is_data diff --git a/plotly/tests/test_core/test_graph_objs/test_plotly_dict.py b/plotly/tests/test_core/test_graph_objs/test_plotly_dict.py index dd66998de3d..c7771930d53 100644 --- a/plotly/tests/test_core/test_graph_objs/test_plotly_dict.py +++ b/plotly/tests/test_core/test_graph_objs/test_plotly_dict.py @@ -8,8 +8,9 @@ from __future__ import absolute_import from nose.tools import raises -from plotly.graph_objs.graph_objs import PlotlyDict + from plotly.exceptions import PlotlyError +from plotly.graph_objs.graph_objs import PlotlyDict def test_trivial(): @@ -28,5 +29,5 @@ def test_validate(): @raises(PlotlyError) def test_validate_error(): pd = PlotlyDict() - pd['invalid']='something' - pd.validate() \ No newline at end of file + pd['invalid'] = 'something' + pd.validate() diff --git a/plotly/tests/test_core/test_graph_objs/test_plotly_list.py b/plotly/tests/test_core/test_graph_objs/test_plotly_list.py index bc1843996c8..8b24ffd8a63 100644 --- a/plotly/tests/test_core/test_graph_objs/test_plotly_list.py +++ b/plotly/tests/test_core/test_graph_objs/test_plotly_list.py @@ -8,8 +8,9 @@ from __future__ import absolute_import from nose.tools import raises -from plotly.graph_objs.graph_objs import PlotlyList, PlotlyDict + from plotly.exceptions import PlotlyError +from plotly.graph_objs.graph_objs import PlotlyList, PlotlyDict def test_trivial(): @@ -38,4 +39,4 @@ def test_validate(): def test_validate_error(): pl = PlotlyList() pl.append({}) - pl.validate() \ No newline at end of file + pl.validate() diff --git a/plotly/tests/test_core/test_graph_objs/test_plotly_trace.py b/plotly/tests/test_core/test_graph_objs/test_plotly_trace.py index 2d04b6890b1..278a487edd0 100644 --- a/plotly/tests/test_core/test_graph_objs/test_plotly_trace.py +++ b/plotly/tests/test_core/test_graph_objs/test_plotly_trace.py @@ -8,8 +8,9 @@ from __future__ import absolute_import from nose.tools import raises -from plotly.graph_objs.graph_objs import PlotlyTrace + from plotly.exceptions import PlotlyError +from plotly.graph_objs.graph_objs import PlotlyTrace def test_trivial(): diff --git a/plotly/tests/test_core/test_graph_objs/test_scatter.py b/plotly/tests/test_core/test_graph_objs/test_scatter.py index 3eaefa27575..13af593784f 100644 --- a/plotly/tests/test_core/test_graph_objs/test_scatter.py +++ b/plotly/tests/test_core/test_graph_objs/test_scatter.py @@ -29,5 +29,5 @@ def test_validate(): @raises(PlotlyError) def test_validate_error(): scatter = Scatter() - scatter['invalid']='something' - scatter.validate() \ No newline at end of file + scatter['invalid'] = 'something' + scatter.validate() diff --git a/plotly/tests/test_core/test_graph_objs/test_strip_style.py b/plotly/tests/test_core/test_graph_objs/test_strip_style.py index 7152eb31497..51d96b17b37 100644 --- a/plotly/tests/test_core/test_graph_objs/test_strip_style.py +++ b/plotly/tests/test_core/test_graph_objs/test_strip_style.py @@ -1,6 +1,7 @@ from __future__ import absolute_import -from plotly.graph_objs import * +from plotly.graph_objs import (Data, Figure, Layout, Line, Margin, Marker, + Scatter, XAxis, YAxis) from plotly.tests.utils import compare_dict @@ -23,11 +24,13 @@ def test_strip_style(): ) ), Scatter( - x=[39317, 37236, 35650, 30066, 29570, 27159, 23557, 21046, 18007], + x=[39317, 37236, 35650, 30066, 29570, 27159, 23557, 21046, + 18007], y=[33, 20, 13, 19, 27, 19, 49, 44, 38], mode='markers', name='Europe', - text=['Germany', 'Britain', 'France', 'Spain', 'Italy', 'Czech Rep.', 'Greece', 'Poland'], + text=['Germany', 'Britain', 'France', 'Spain', 'Italy', + 'Czech Rep.', 'Greece', 'Poland'], marker=Marker( color='rgb(255, 217, 102)', size=12, @@ -42,7 +45,8 @@ def test_strip_style(): y=[23, 42, 54, 89, 14, 99, 93, 70], mode='markers', name='Asia/Pacific', - text=['Australia', 'Japan', 'South Korea', 'Malaysia', 'China', 'Indonesia', 'Philippines', 'India'], + text=['Australia', 'Japan', 'South Korea', 'Malaysia', 'China', + 'Indonesia', 'Philippines', 'India'], marker=Marker( color='rgb(234, 153, 153)', size=12, @@ -57,7 +61,8 @@ def test_strip_style(): y=[43, 47, 56, 80, 86, 93, 80], mode='markers', name='Latin America', - text=['Chile', 'Argentina', 'Mexico', 'Venezuela', 'Venezuela', 'El Salvador', 'Bolivia'], + text=['Chile', 'Argentina', 'Mexico', 'Venezuela', 'Venezuela', + 'El Salvador', 'Bolivia'], marker=Marker( color='rgb(142, 124, 195)', size=12, @@ -108,11 +113,13 @@ def test_strip_style(): ) ), Scatter( - x=[39317, 37236, 35650, 30066, 29570, 27159, 23557, 21046, 18007], + x=[39317, 37236, 35650, 30066, 29570, 27159, 23557, 21046, + 18007], y=[33, 20, 13, 19, 27, 19, 49, 44, 38], mode='markers', name='Europe', - text=['Germany', 'Britain', 'France', 'Spain', 'Italy', 'Czech Rep.', 'Greece', 'Poland'], + text=['Germany', 'Britain', 'France', 'Spain', 'Italy', + 'Czech Rep.', 'Greece', 'Poland'], marker=Marker( line=Line() ) @@ -122,7 +129,8 @@ def test_strip_style(): y=[23, 42, 54, 89, 14, 99, 93, 70], mode='markers', name='Asia/Pacific', - text=['Australia', 'Japan', 'South Korea', 'Malaysia', 'China', 'Indonesia', 'Philippines', 'India'], + text=['Australia', 'Japan', 'South Korea', 'Malaysia', 'China', + 'Indonesia', 'Philippines', 'India'], marker=Marker( line=Line() ) @@ -132,7 +140,8 @@ def test_strip_style(): y=[43, 47, 56, 80, 86, 93, 80], mode='markers', name='Latin America', - text=['Chile', 'Argentina', 'Mexico', 'Venezuela', 'Venezuela', 'El Salvador', 'Bolivia'], + text=['Chile', 'Argentina', 'Mexico', 'Venezuela', 'Venezuela', + 'El Salvador', 'Bolivia'], marker=Marker( line=Line() ) diff --git a/plotly/tests/test_core/test_graph_objs/test_to_string.py b/plotly/tests/test_core/test_graph_objs/test_to_string.py index c779b9ad095..a5d9ec14975 100644 --- a/plotly/tests/test_core/test_graph_objs/test_to_string.py +++ b/plotly/tests/test_core/test_graph_objs/test_to_string.py @@ -1,6 +1,6 @@ from __future__ import absolute_import -from plotly.graph_objs import * +from plotly.graph_objs import Contour, Data, Figure, Layout, Margin, Scatter def test_to_string(): @@ -28,7 +28,29 @@ def test_to_string(): ) ) fig_string = fig.to_string(pretty=False) - comp_string = 'Figure(\n data=Data([\n Scatter(\n x=[1, 2, 3, 4],\n y=[10, 15, 13, 17]\n ),\n Scatter(\n x=[1, 2, 3, 4],\n y=[16, 5, 11, 9]\n )\n ]),\n layout=Layout(\n autosize=False,\n width=500,\n height=500,\n margin=Margin(\n l=65,\n r=50,\n b=65,\n t=65\n )\n )\n)' + comp_string = ('Figure(\n' + ' data=Data([\n' + ' Scatter(\n' + ' x=[1, 2, 3, 4],\n' + ' y=[10, 15, 13, 17]\n' + ' ),\n' + ' Scatter(\n' + ' x=[1, 2, 3, 4],\n' + ' y=[16, 5, 11, 9]\n' + ' )\n' + ' ]),\n' + ' layout=Layout(\n' + ' autosize=False,\n' + ' width=500,\n' + ' height=500,\n' + ' margin=Margin(\n' + ' l=65,\n' + ' r=50,\n' + ' b=65,\n' + ' t=65\n' + ' )\n' + ' )\n' + ')') assert fig_string == comp_string diff --git a/plotly/tests/test_core/test_graph_objs/test_update.py b/plotly/tests/test_core/test_graph_objs/test_update.py index 45a03cd8ceb..57eeadc4d0a 100644 --- a/plotly/tests/test_core/test_graph_objs/test_update.py +++ b/plotly/tests/test_core/test_graph_objs/test_update.py @@ -1,6 +1,6 @@ from __future__ import absolute_import -from plotly.graph_objs import * +from plotly.graph_objs import Data, Figure, Layout, Line, Scatter, XAxis def test_update_dict(): @@ -11,49 +11,50 @@ def test_update_dict(): fig['layout'].update(xaxis=XAxis()) assert fig == Figure(layout=Layout(title=title, xaxis=XAxis())) + def test_update_list(): - trace1 = Scatter(x=[1,2,3], y=[2,1,2]) - trace2 = Scatter(x=[1,2,3], y=[3,2,1]) + trace1 = Scatter(x=[1, 2, 3], y=[2, 1, 2]) + trace2 = Scatter(x=[1, 2, 3], y=[3, 2, 1]) data = Data([trace1, trace2]) - update = dict(x=[2,3,4], y=[1,2,3]) + update = dict(x=[2, 3, 4], y=[1, 2, 3]) data.update(update) - assert data[0] == Scatter(x=[2,3,4], y=[1,2,3]) - assert data[1] == Scatter(x=[2,3,4], y=[1,2,3]) + assert data[0] == Scatter(x=[2, 3, 4], y=[1, 2, 3]) + assert data[1] == Scatter(x=[2, 3, 4], y=[1, 2, 3]) def test_update_dict_empty(): - trace1 = Scatter(x=[1,2,3], y=[2,1,2]) - trace2 = Scatter(x=[1,2,3], y=[3,2,1]) + trace1 = Scatter(x=[1, 2, 3], y=[2, 1, 2]) + trace2 = Scatter(x=[1, 2, 3], y=[3, 2, 1]) data = Data([trace1, trace2]) data.update({}) print(data.to_string()) - assert data[0] == Scatter(x=[1,2,3], y=[2,1,2]) - assert data[1] == Scatter(x=[1,2,3], y=[3,2,1]) + assert data[0] == Scatter(x=[1, 2, 3], y=[2, 1, 2]) + assert data[1] == Scatter(x=[1, 2, 3], y=[3, 2, 1]) def test_update_list_empty(): - trace1 = Scatter(x=[1,2,3], y=[2,1,2]) - trace2 = Scatter(x=[1,2,3], y=[3,2,1]) + trace1 = Scatter(x=[1, 2, 3], y=[2, 1, 2]) + trace2 = Scatter(x=[1, 2, 3], y=[3, 2, 1]) data = Data([trace1, trace2]) data.update([]) print(data.to_string()) - assert data[0] == Scatter(x=[1,2,3], y=[2,1,2]) - assert data[1] == Scatter(x=[1,2,3], y=[3,2,1]) + assert data[0] == Scatter(x=[1, 2, 3], y=[2, 1, 2]) + assert data[1] == Scatter(x=[1, 2, 3], y=[3, 2, 1]) def test_update_list_make_copies_false(): - trace1 = Scatter(x=[1,2,3], y=[2,1,2]) - trace2 = Scatter(x=[1,2,3], y=[3,2,1]) + trace1 = Scatter(x=[1, 2, 3], y=[2, 1, 2]) + trace2 = Scatter(x=[1, 2, 3], y=[3, 2, 1]) data = Data([trace1, trace2]) - update = dict(x=[2,3,4], y=[1,2,3], line=Line()) + update = dict(x=[2, 3, 4], y=[1, 2, 3], line=Line()) data.update(update, make_copies=False) assert data[0]['line'] is data[1]['line'] def test_update_list_make_copies_true(): - trace1 = Scatter(x=[1,2,3], y=[2,1,2]) - trace2 = Scatter(x=[1,2,3], y=[3,2,1]) + trace1 = Scatter(x=[1, 2, 3], y=[2, 1, 2]) + trace2 = Scatter(x=[1, 2, 3], y=[3, 2, 1]) data = Data([trace1, trace2]) - update = dict(x=[2,3,4], y=[1,2,3], line=Line()) + update = dict(x=[2, 3, 4], y=[1, 2, 3], line=Line()) data.update(update, make_copies=True) assert data[0]['line'] is not data[1]['line'] diff --git a/plotly/tests/test_core/test_graph_reference/__init__.py b/plotly/tests/test_core/test_graph_reference/__init__.py index d18b2e7d500..1118eb01e82 100644 --- a/plotly/tests/test_core/test_graph_reference/__init__.py +++ b/plotly/tests/test_core/test_graph_reference/__init__.py @@ -1,7 +1,5 @@ -def setup_package(): - import warnings - warnings.filterwarnings('ignore') +import warnings -def teardown_package(): - pass +def setup_package(): + warnings.filterwarnings('ignore') diff --git a/plotly/tests/test_core/test_graph_reference/test_key_types.py b/plotly/tests/test_core/test_graph_reference/test_key_types.py index 6b2df0e1993..454ad320ffb 100644 --- a/plotly/tests/test_core/test_graph_reference/test_key_types.py +++ b/plotly/tests/test_core/test_graph_reference/test_key_types.py @@ -13,10 +13,11 @@ def test_style_exists(): checks = True for obj, stuff in list(go.INFO.items()): - if obj not in ['plotlylist', 'data', 'annotations', 'plotlydict', 'plotlytrace', 'trace']: + if obj not in ['plotlylist', 'data', 'annotations', 'plotlydict', + 'plotlytrace', 'trace']: for attr_key, attr in list(stuff['keymeta'].items()): if 'key_type' not in attr: checks = False - print(obj_key, attr_key) + print(obj, attr_key) if not checks: raise Exception diff --git a/plotly/tests/test_core/test_grid/test_grid.py b/plotly/tests/test_core/test_grid/test_grid.py index 830f48202e9..a3baabf06e4 100644 --- a/plotly/tests/test_core/test_grid/test_grid.py +++ b/plotly/tests/test_core/test_grid/test_grid.py @@ -5,20 +5,19 @@ A module intended for use with Nose. """ - -from nose.tools import raises -from nose import with_setup -from nose.plugins.attrib import attr +from __future__ import absolute_import import random import string -from plotly.graph_objs import Scatter +from nose import with_setup +from nose.tools import raises + import plotly.plotly as py -from plotly.plotly.plotly import _api_v2 -import plotly.tools as tls -from plotly.grid_objs import Column, Grid from plotly.exceptions import InputError, PlotlyRequestError +from plotly.graph_objs import Scatter +from plotly.grid_objs import Column, Grid +from plotly.plotly.plotly import _api_v2 def random_filename(): @@ -47,7 +46,7 @@ def upload_and_return_grid(): return g -## Nominal usage +# Nominal usage def test_grid_upload(): upload_and_return_grid() @@ -68,7 +67,7 @@ def test_grid_upload_in_existing_folder(): folder = random_filename() filename = random_filename() py.file_ops.mkdirs(folder) - path =( + path = ( 'existing folder: {0}/grid in folder {1}' .format(folder, filename) ) @@ -105,7 +104,7 @@ def test_get_figure_from_references(): assert(g[0].data == trace['x']) assert(g[1].data == trace['y']) -## Test grid args +# Test grid args _grid_id = 'chris:3043' _grid = Grid([]) _grid.id = _grid_id @@ -129,7 +128,7 @@ def test_overspecified_grid_args(): _api_v2.parse_grid_id_args(_grid, _grid_url) -## Out of order usage +# Out of order usage @raises(InputError) def test_scatter_from_non_uploaded_grid(): c1 = Column([1, 2, 3, 4], 'first column') @@ -155,7 +154,7 @@ def test_row_append_of_non_uploaded_grid(): py.grid_ops.append_rows(rows, grid=g) -## Input Errors +# Input Errors @raises(InputError) def test_unequal_length_rows(): g = upload_and_return_grid() @@ -181,7 +180,7 @@ def test_delete_grid(): py.grid_ops.upload(g, fn, auto_open=False) -## Plotly failures +# Plotly failures def test_duplicate_filenames(): c1 = Column([1, 2, 3, 4], 'first column') g = Grid([c1]) diff --git a/plotly/tests/test_core/test_meta/test_meta.py b/plotly/tests/test_core/test_meta/test_meta.py index f64d388650b..ec101f89079 100644 --- a/plotly/tests/test_core/test_meta/test_meta.py +++ b/plotly/tests/test_core/test_meta/test_meta.py @@ -5,18 +5,17 @@ A module intended for use with Nose. """ - -from nose.tools import raises -from nose import with_setup +from __future__ import absolute_import import random import string -import requests + +from nose import with_setup +from nose.tools import raises import plotly.plotly as py -import plotly.tools as tls -from plotly.grid_objs import Column, Grid from plotly.exceptions import PlotlyRequestError +from plotly.grid_objs import Column, Grid def init(): @@ -24,7 +23,8 @@ def init(): _grid = grid = Grid([Column([1, 2, 3, 4], 'first column')]) -_meta = {"settings":{"scope1":{"model":"Unicorn Finder","voltage":4}}} +_meta = {"settings": {"scope1": {"model": "Unicorn Finder", "voltage": 4}}} + def _random_filename(): random_chars = [random.choice(string.ascii_uppercase) for _ in range(5)] @@ -38,15 +38,13 @@ def test_upload_meta(): grid_url = py.grid_ops.upload(_grid, unique_filename, auto_open=False) # Add some Metadata to that grid - meta_url = py.meta_ops.upload( - _meta, - grid_url=grid_url) + py.meta_ops.upload(_meta, grid_url=grid_url) @with_setup(init) def test_upload_meta_with_grid(): c1 = Column([1, 2, 3, 4], 'first column') - grid = Grid([c1]) + Grid([c1]) unique_filename = _random_filename() @@ -63,6 +61,4 @@ def test_metadata_to_nonexistent_grid(): non_exist_meta_url = 'https://local.plot.ly/~GridTest/999999999' - meta_url = py.meta_ops.upload( - _meta, - grid_url=non_exist_meta_url) + py.meta_ops.upload(_meta, grid_url=non_exist_meta_url) diff --git a/plotly/tests/test_core/test_offline/__init__.py b/plotly/tests/test_core/test_offline/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/plotly/tests/test_core/test_plotly/__init__.py b/plotly/tests/test_core/test_plotly/__init__.py index 329fe200223..1118eb01e82 100644 --- a/plotly/tests/test_core/test_plotly/__init__.py +++ b/plotly/tests/test_core/test_plotly/__init__.py @@ -1,7 +1,5 @@ -def setup_package(): - import warnings - warnings.filterwarnings('ignore') +import warnings -def teardown_package(): - pass \ No newline at end of file +def setup_package(): + warnings.filterwarnings('ignore') diff --git a/plotly/tests/test_core/test_plotly/test_credentials.py b/plotly/tests/test_core/test_plotly/test_credentials.py index bd075adfa3a..573b30c91b0 100644 --- a/plotly/tests/test_core/test_plotly/test_credentials.py +++ b/plotly/tests/test_core/test_plotly/test_credentials.py @@ -1,7 +1,10 @@ +from __future__ import absolute_import + from unittest import TestCase + import plotly.plotly.plotly as py -import plotly.tools as tls import plotly.session as session +import plotly.tools as tls def test_get_credentials(): diff --git a/plotly/tests/test_core/test_plotly/test_plot.py b/plotly/tests/test_core/test_plotly/test_plot.py index 6d94ba267b3..bfa93516e79 100644 --- a/plotly/tests/test_core/test_plotly/test_plot.py +++ b/plotly/tests/test_core/test_plotly/test_plot.py @@ -6,17 +6,19 @@ """ from __future__ import absolute_import -from nose.tools import raises + from unittest import TestCase -from plotly.graph_objs import graph_objs -from plotly.plotly import plotly as py +from nose.tools import raises + from plotly.exceptions import PlotlyError, PlotlyEmptyDataError +from plotly.plotly import plotly as py # username for tests: 'PlotlyImageTest' # api_key for account: '786r5mecv0' + def setUp(): py.sign_in('PlotlyImageTest', '786r5mecv0', plotly_domain='https://plot.ly') @@ -24,41 +26,38 @@ def setUp(): def test_plot_valid(): fig = { - 'data':[ + 'data': [ { - 'x':[1,2,3], - 'y':[2,1,2] + 'x': [1, 2, 3], + 'y': [2, 1, 2] } ] } - url = py.plot(fig, auto_open=False, filename='plot_valid') + py.plot(fig, auto_open=False, filename='plot_valid') @raises(PlotlyError) def test_plot_invalid(): fig = { - 'data':[ + 'data': [ { - 'x':[1,2,3], - 'y':[2,1,2], - 'z':[3,4,1] + 'x': [1, 2, 3], + 'y': [2, 1, 2], + 'z': [3, 4, 1] } ] } - url = py.plot(fig, auto_open=False, filename='plot_invalid') + py.plot(fig, auto_open=False, filename='plot_invalid') + @raises(TypeError) def test_plot_invalid_args_1(): - url = py.plot(x=[1,2,3], - y=[2,1,2], - auto_open=False, - filename='plot_invalid') + py.plot(x=[1, 2, 3], y=[2, 1, 2], auto_open=False, filename='plot_invalid') + @raises(PlotlyError) def test_plot_invalid_args_2(): - url = py.plot([1,2,3], [2,1,2], - auto_open=False, - filename='plot_invalid') + py.plot([1, 2, 3], [2, 1, 2], auto_open=False, filename='plot_invalid') class TestPlot(TestCase): @@ -67,35 +66,3 @@ def test_plot_empty_data(self): py.sign_in('PlotlyImageTest', '786r5mecv0') self.assertRaises(PlotlyEmptyDataError, py.plot, [], filename='plot_invalid') - - -def test_bar(): - pass - - -def test_box(): - pass - - -def test_contour(): - pass - - -def test_heatmap(): - pass - - -def test_histogram(): - pass - - -def test_histogram2d(): - pass - - -def test_histogram2dcontour(): - pass - - -def test_plot_scatter(): - pass diff --git a/plotly/tests/test_core/test_stream/__init__.py b/plotly/tests/test_core/test_stream/__init__.py index 73f1ee4bb1e..e69de29bb2d 100644 --- a/plotly/tests/test_core/test_stream/__init__.py +++ b/plotly/tests/test_core/test_stream/__init__.py @@ -1,6 +0,0 @@ -def setup_package(): - pass - - -def teardown_package(): - pass \ No newline at end of file diff --git a/plotly/tests/test_core/test_stream/test_stream.py b/plotly/tests/test_core/test_stream/test_stream.py index a08770b12a0..7e65b3d8e94 100644 --- a/plotly/tests/test_core/test_stream/test_stream.py +++ b/plotly/tests/test_core/test_stream/test_stream.py @@ -8,9 +8,11 @@ from __future__ import absolute_import import time + from nose.tools import raises -from plotly.graph_objs import * + import plotly.plotly as py +from plotly.graph_objs import (Layout, Scatter, Stream) from plotly import exceptions un = 'PythonAPI' diff --git a/plotly/tests/test_core/test_tools/__init__.py b/plotly/tests/test_core/test_tools/__init__.py index 329fe200223..f367e6011a3 100644 --- a/plotly/tests/test_core/test_tools/__init__.py +++ b/plotly/tests/test_core/test_tools/__init__.py @@ -1,7 +1,4 @@ +import warnings + def setup_package(): - import warnings warnings.filterwarnings('ignore') - - -def teardown_package(): - pass \ No newline at end of file diff --git a/plotly/tests/test_core/test_tools/test_file_tools.py b/plotly/tests/test_core/test_tools/test_file_tools.py index 102e108c013..28540146de9 100644 --- a/plotly/tests/test_core/test_tools/test_file_tools.py +++ b/plotly/tests/test_core/test_tools/test_file_tools.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import + import plotly.tools as tls diff --git a/plotly/tests/test_core/test_tools/test_get_embed.py b/plotly/tests/test_core/test_tools/test_get_embed.py index e384b4f65b4..cf64613dbbc 100644 --- a/plotly/tests/test_core/test_tools/test_get_embed.py +++ b/plotly/tests/test_core/test_tools/test_get_embed.py @@ -1,14 +1,17 @@ -import plotly.tools as tls +from __future__ import absolute_import + from nose.tools import raises + +import plotly.tools as tls from plotly.exceptions import PlotlyError def test_get_valid_embed(): url = 'https://plot.ly/~PlotBot/82/' - embed = tls.get_embed(url) + tls.get_embed(url) @raises(PlotlyError) def test_get_invalid_embed(): url = 'https://plot.ly/~PlotBot/a/' - embed = tls.get_embed(url) + tls.get_embed(url) diff --git a/plotly/tests/test_core/test_tools/test_get_subplots.py b/plotly/tests/test_core/test_tools/test_get_subplots.py index 026dffebff5..5ae2d756f7c 100644 --- a/plotly/tests/test_core/test_tools/test_get_subplots.py +++ b/plotly/tests/test_core/test_tools/test_get_subplots.py @@ -1,28 +1,35 @@ -import plotly -from plotly.graph_objs import * -import plotly.tools as tls +from __future__ import absolute_import + from nose.tools import raises +from plotly.graph_objs import (Data, Figure, Layout, XAxis, YAxis) +import plotly.tools as tls + @raises(Exception) def test_non_integer_rows(): - fig = tls.get_subplots(rows=2.1) + tls.get_subplots(rows=2.1) + @raises(Exception) def test_less_than_zero_rows(): - fig = tls.make_subplots(rows=-2) + tls.make_subplots(rows=-2) + @raises(Exception) def test_non_integer_columns(): - fig = tls.get_subplots(columns=2/3) + tls.get_subplots(columns=2/3) + @raises(Exception) def test_less_than_zero_cols(): - fig = tls.make_subplots(columns=-10) + tls.make_subplots(columns=-10) + @raises(Exception) def test_wrong_kwarg(): - fig = tls.get_subplots(stuff='no gonna work') + tls.get_subplots(stuff='no gonna work') + def test_get_single_plot(): expected = Figure( @@ -40,6 +47,7 @@ def test_get_single_plot(): ) assert tls.get_subplots() == expected + def test_two_row(): expected = Figure( data=Data(), @@ -90,6 +98,7 @@ def test_two_column(): assert tls.get_subplots(1, 2) == expected + def test_a_lot(): expected = Figure( data=Data(), @@ -321,12 +330,11 @@ def test_a_lot(): ) ) - fig = tls.get_subplots(4, 7, - horizontal_spacing=0.1, - vertical_spacing=0.15) + fig = tls.get_subplots(4, 7, horizontal_spacing=0.1, vertical_spacing=0.15) assert fig == expected + def test_spacing(): expected = Figure( data=Data(), @@ -388,6 +396,7 @@ def test_spacing(): assert fig == expected + def test_default_spacing(): expected = Figure( data=Data(), diff --git a/plotly/tests/test_core/test_tools/test_make_subplots.py b/plotly/tests/test_core/test_tools/test_make_subplots.py index 6f7744843c1..a96e71dde00 100644 --- a/plotly/tests/test_core/test_tools/test_make_subplots.py +++ b/plotly/tests/test_core/test_tools/test_make_subplots.py @@ -1,98 +1,118 @@ -import plotly -from plotly.graph_objs import * -import plotly.tools as tls +from __future__ import absolute_import + from nose.tools import raises +from plotly.graph_objs import (Annotation, Annotations, Data, Figure, Font, + Layout, Scene, XAxis, YAxis) +import plotly.tools as tls + @raises(Exception) def test_non_integer_rows(): - fig = tls.make_subplots(rows=2.1) + tls.make_subplots(rows=2.1) + @raises(Exception) def test_less_than_zero_rows(): - fig = tls.make_subplots(rows=-2) + tls.make_subplots(rows=-2) + @raises(Exception) def test_non_integer_cols(): - fig = tls.make_subplots(cols=2/3) + tls.make_subplots(cols=2/3) + @raises(Exception) def test_less_than_zero_cols(): - fig = tls.make_subplots(cols=-10) + tls.make_subplots(cols=-10) + @raises(Exception) def test_wrong_kwarg(): - fig = tls.make_subplots(stuff='no gonna work') + tls.make_subplots(stuff='no gonna work') + @raises(Exception) def test_non_integer_rows(): - fig = tls.make_subplots(rows=2.1) + tls.make_subplots(rows=2.1) + @raises(Exception) def test_non_integer_cols(): - fig = tls.make_subplots(cols=2/3) + tls.make_subplots(cols=2/3) + @raises(Exception) def test_wrong_kwarg(): - fig = tls.make_subplots(stuff='no gonna work') + tls.make_subplots(stuff='no gonna work') + @raises(Exception) def test_start_cell_wrong_values(): - fig = tls.make_subplots(rows=2, cols=2, start_cell='not gonna work') + tls.make_subplots(rows=2, cols=2, start_cell='not gonna work') + @raises(Exception) def test_specs_wrong_type(): - fig = tls.make_subplots(specs="not going to work") + tls.make_subplots(specs="not going to work") + @raises(Exception) def test_specs_wrong_inner_type(): - fig = tls.make_subplots(specs=[{}]) + tls.make_subplots(specs=[{}]) + @raises(Exception) def test_specs_wrong_item_type(): - fig = tls.make_subplots(specs=[[('not', 'going to work')]]) + tls.make_subplots(specs=[[('not', 'going to work')]]) + @raises(Exception) def test_specs_wrong_item_key(): - fig = tls.make_subplots(specs=[{'not': "going to work"}]) + tls.make_subplots(specs=[{'not': "going to work"}]) + @raises(Exception) def test_specs_underspecified(): - fig = tls.make_subplots(rows=2, specs=[{}]) - fig = tls.make_subplots(rows=2, cols=2, specs=[[{}, {}], [{}]]) + tls.make_subplots(rows=2, specs=[{}]) + tls.make_subplots(rows=2, cols=2, specs=[[{}, {}], [{}]]) + @raises(Exception) def test_specs_overspecified(): - fig = tls.make_subplots(rows=2, specs=[[{}], [{}], [{}]]) - fig = tls.make_subplots(cols=2, specs=[{}, {}, {}]) + tls.make_subplots(rows=2, specs=[[{}], [{}], [{}]]) + tls.make_subplots(cols=2, specs=[{}, {}, {}]) + @raises(Exception) def test_specs_colspan_too_big(): - fig = tls.make_subplots(cols=3, - specs=[[{}, None, {'colspan': 2}]]) + tls.make_subplots(cols=3, specs=[[{}, None, {'colspan': 2}]]) + @raises(Exception) def test_specs_rowspan_too_big(): - fig = tls.make_subplots(rows=3, - specs=[[{}], - [None], - [{'rowspan': 2}]]) + tls.make_subplots(rows=3, specs=[[{}], [None], [{'rowspan': 2}]]) + @raises(Exception) def test_insets_wrong_type(): - fig = tls.make_subplots(insets="not going to work") + tls.make_subplots(insets="not going to work") + @raises(Exception) def test_insets_wrong_item(): - fig = tls.make_subplots(insets=[{'not': "going to work"}]) + tls.make_subplots(insets=[{'not': "going to work"}]) + @raises(Exception) def test_insets_wrong_cell_row(): - fig = tls.make_subplots(insets=([{'cell': (0, 1)}])) + tls.make_subplots(insets=([{'cell': (0, 1)}])) + @raises(Exception) def test_insets_wrong_cell_col(): - fig = tls.make_subplots(insets=([{'cell': (1, 0)}])) + tls.make_subplots(insets=([{'cell': (1, 0)}])) + def test_single_plot(): expected = Figure( @@ -110,6 +130,7 @@ def test_single_plot(): ) assert tls.make_subplots() == expected + def test_two_row(): expected = Figure( data=Data(), @@ -134,6 +155,7 @@ def test_two_row(): ) assert tls.make_subplots(rows=2) == expected + def test_two_row_bottom_left(): expected = Figure( data=Data(), @@ -160,6 +182,7 @@ def test_two_row_bottom_left(): fig = tls.make_subplots(rows=2, start_cell='bottom-left') assert fig == expected + def test_two_column(): expected = Figure( data=Data(), @@ -184,6 +207,7 @@ def test_two_column(): ) assert tls.make_subplots(cols=2) == expected + def test_a_lot(): expected = Figure( data=Data(), @@ -418,6 +442,7 @@ def test_a_lot(): fig = tls.make_subplots(rows=4, cols=7) assert fig == expected + def test_a_lot_bottom_left(): expected = Figure( data=Data(), @@ -652,6 +677,7 @@ def test_a_lot_bottom_left(): fig = tls.make_subplots(rows=4, cols=7, start_cell='bottom-left') assert fig == expected + def test_spacing(): expected = Figure( data=Data(), @@ -708,12 +734,13 @@ def test_spacing(): ) fig = tls.make_subplots(rows=2, cols=3, - horizontal_spacing=.05, - vertical_spacing=.1) + horizontal_spacing=.05, + vertical_spacing=.1) assert fig == expected + def test_specs(): - expected = Figure( + expected = Figure( data=Data(), layout=Layout( xaxis1=XAxis( @@ -756,8 +783,9 @@ def test_specs(): [{}, {}, {}]]) assert fig == expected + def test_specs_bottom_left(): - expected = Figure( + expected = Figure( data=Data(), layout=Layout( xaxis1=XAxis( @@ -801,6 +829,7 @@ def test_specs_bottom_left(): start_cell='bottom-left') assert fig == expected + def test_specs_colspan(): expected = Figure( data=Data(), @@ -849,11 +878,12 @@ def test_specs_colspan(): ) fig = tls.make_subplots(rows=3, cols=2, - specs=[[{'colspan':2}, None], + specs=[[{'colspan': 2}, None], [{}, {}], [{}, {}]]) assert fig == expected + def test_specs_rowspan(): expected = Figure( data=Data(), @@ -909,12 +939,11 @@ def test_specs_rowspan(): ) ) - fig = tls.make_subplots(rows=3, cols=3, - specs=[[{'rowspan': 3}, {}, {}], - [None, {}, {}], - [None, {'colspan': 2}, None]]) + fig = tls.make_subplots(rows=3, cols=3, specs=[[{'rowspan': 3}, {}, {}], + [None, {}, {}], [None, {'colspan': 2}, None]]) assert fig == expected + def test_specs_rowspan2(): expected = Figure( data=Data(), @@ -962,12 +991,12 @@ def test_specs_rowspan2(): ) ) - fig = tls.make_subplots(rows=3, cols=3, - specs=[[{}, {}, {'rowspan': 2}], - [{'colspan': 2}, None, None], - [{'colspan': 3}, None, None]]) + fig = tls.make_subplots(rows=3, cols=3, specs=[[{}, {}, {'rowspan': 2}], + [{'colspan': 2}, None, None], + [{'colspan': 3}, None, None]]) assert fig == expected + def test_specs_colspan_rowpan(): expected = Figure( data=Data(), @@ -1024,11 +1053,11 @@ def test_specs_colspan_rowpan(): ) fig = tls.make_subplots(rows=3, cols=3, - specs=[[{'colspan': 2, 'rowspan': 2}, None, {}], - [None, None, {}], - [{}, {}, {}]]) + specs=[[{'colspan': 2, 'rowspan': 2}, None, {}], + [None, None, {}], [{}, {}, {}]]) assert fig == expected + def test_specs_colspan_rowpan_bottom_left(): expected = Figure( data=Data(), @@ -1086,11 +1115,11 @@ def test_specs_colspan_rowpan_bottom_left(): fig = tls.make_subplots(rows=3, cols=3, specs=[[{'colspan': 2, 'rowspan': 2}, None, {}], - [None, None, {}], - [{}, {}, {}]], + [None, None, {}], [{}, {}, {}]], start_cell='bottom-left') assert fig == expected + def test_specs_is_3d(): expected = Figure( data=Data(), @@ -1120,11 +1149,11 @@ def test_specs_is_3d(): ) ) - fig = tls.make_subplots(rows=2, cols=2, - specs=[[{'is_3d': True}, {}], - [{'is_3d': True}, {}]]) + fig = tls.make_subplots(rows=2, cols=2, specs=[[{'is_3d': True}, {}], + [{'is_3d': True}, {}]]) assert fig == expected + def test_specs_padding(): expected = Figure( data=Data(), @@ -1164,12 +1193,13 @@ def test_specs_padding(): ) ) - fig = tls.make_subplots(rows=2, cols=2, - horizontal_spacing=0, vertical_spacing=0, - specs=[[{'l': 0.1}, {'b': 0.2}], - [{'t': 0.2}, {'r': 0.1}]]) + fig = tls.make_subplots(rows=2, cols=2, horizontal_spacing=0, + vertical_spacing=0, + specs=[[{'l': 0.1}, {'b': 0.2}], + [{'t': 0.2}, {'r': 0.1}]]) assert fig == expected + def test_specs_padding_bottom_left(): expected = Figure( data=Data(), @@ -1216,6 +1246,7 @@ def test_specs_padding_bottom_left(): start_cell='bottom-left') assert fig == expected + def test_shared_xaxes(): expected = Figure( data=Data(), @@ -1265,6 +1296,7 @@ def test_shared_xaxes(): fig = tls.make_subplots(rows=2, cols=3, shared_xaxes=True) assert fig == expected + def test_shared_xaxes_bottom_left(): expected = Figure( data=Data(), @@ -1315,79 +1347,6 @@ def test_shared_xaxes_bottom_left(): shared_xaxes=True, start_cell='bottom-left') assert fig == expected -def test_shared_yaxes(): - expected = Figure( - data=Data(), - layout=Layout( - xaxis1=XAxis( - domain=[0.0, 0.45], - anchor='y1' - ), - xaxis10=XAxis( - domain=[0.55, 1.0], - anchor='free' - ), - xaxis2=XAxis( - domain=[0.55, 1.0], - anchor='free', - position=0.848 - ), - xaxis3=XAxis( - domain=[0.0, 0.45], - anchor='y2' - ), - xaxis4=XAxis( - domain=[0.55, 1.0], - anchor='free', - position=0.636 - ), - xaxis5=XAxis( - domain=[0.0, 0.45], - anchor='y3' - ), - xaxis6=XAxis( - domain=[0.55, 1.0], - anchor='free', - position=0.424 - ), - xaxis7=XAxis( - domain=[0.0, 0.45], - anchor='y4' - ), - xaxis8=XAxis( - domain=[0.55, 1.0], - anchor='free', - position=0.212 - ), - xaxis9=XAxis( - domain=[0.0, 0.45], - anchor='y5' - ), - yaxis1=YAxis( - domain=[0.848, 1.0], - anchor='x1' - ), - yaxis2=YAxis( - domain=[0.636, 0.788], - anchor='x3' - ), - yaxis3=YAxis( - domain=[0.424, 0.576], - anchor='x5' - ), - yaxis4=YAxis( - domain=[0.212, 0.364], - anchor='x7' - ), - yaxis5=YAxis( - domain=[0.0, 0.152], - anchor='x9' - ) - ) - ) - - fig = tls.make_subplots(rows=5, cols=2, shared_yaxes=True) - assert fig == expected def test_shared_yaxes(): expected = Figure( @@ -1464,6 +1423,7 @@ def test_shared_yaxes(): fig = tls.make_subplots(rows=5, cols=2, shared_yaxes=True) assert fig == expected + def test_shared_xaxes_yaxes(): expected = Figure( data=Data(), @@ -1544,6 +1504,7 @@ def test_shared_xaxes_yaxes_bottom_left(): start_cell='bottom-left') assert fig == expected + def test_shared_axes_list(): expected = Figure( data=Data(), @@ -1577,11 +1538,11 @@ def test_shared_axes_list(): ) ) - fig = tls.make_subplots(rows=2, cols=2, - shared_xaxes=[(1,1), (2,1)], - shared_yaxes=[(1,1), (1,2)]) + fig = tls.make_subplots(rows=2, cols=2, shared_xaxes=[(1, 1), (2, 1)], + shared_yaxes=[(1, 1), (1, 2)]) assert fig == expected + def test_shared_axes_list_bottom_left(): expected = Figure( data=Data(), @@ -1615,12 +1576,12 @@ def test_shared_axes_list_bottom_left(): ) ) - fig = tls.make_subplots(rows=2, cols=2, - shared_xaxes=[(1,1), (2,1)], - shared_yaxes=[(1,1), (1,2)], + fig = tls.make_subplots(rows=2, cols=2, shared_xaxes=[(1, 1), (2, 1)], + shared_yaxes=[(1, 1), (1, 2)], start_cell='bottom-left') assert fig == expected + def test_shared_axes_list_of_lists(): expected = Figure( data=Data(), @@ -1670,9 +1631,8 @@ def test_shared_axes_list_of_lists(): ) ) - fig = tls.make_subplots(rows=2, cols=3, - shared_xaxes=[[(1,1), (2,1)], - [(1,3), (2,3)]]) + fig = tls.make_subplots(rows=2, cols=3, shared_xaxes=[[(1, 1), (2, 1)], + [(1, 3), (2, 3)]]) assert fig == expected @@ -1725,12 +1685,12 @@ def test_shared_axes_list_of_lists_bottom_left(): ) ) - fig = tls.make_subplots(rows=2, cols=3, - shared_xaxes=[[(1,1), (2,1)], - [(1,3), (2,3)]], + fig = tls.make_subplots(rows=2, cols=3, shared_xaxes=[[(1, 1), (2, 1)], + [(1, 3), (2, 3)]], start_cell='bottom-left') assert fig == expected + def test_insets(): expected = Figure( data=Data(), @@ -1779,11 +1739,11 @@ def test_insets(): ) fig = tls.make_subplots(rows=2, cols=2, - insets=[{'cell': (2,2), - 'l': 0.7, 'w': 0.2, + insets=[{'cell': (2, 2), 'l': 0.7, 'w': 0.2, 'b': 0.2, 'h': 0.5}]) assert fig == expected + def test_insets_bottom_left(): expected = Figure( data=Data(), @@ -1832,12 +1792,12 @@ def test_insets_bottom_left(): ) fig = tls.make_subplots(rows=2, cols=2, - insets=[{'cell': (2,2), - 'l': 0.7, 'w': 0.2, + insets=[{'cell': (2, 2), 'l': 0.7, 'w': 0.2, 'b': 0.2, 'h': 0.5}], start_cell='bottom-left') assert fig == expected + def test_insets_multiple(): expected = Figure( data=Data(), @@ -1877,11 +1837,11 @@ def test_insets_multiple(): ) ) - fig = tls.make_subplots(rows=2, - insets=[{'cell': (1,1), 'l':0.8}, - {'cell': (2,1), 'l':0.8}]) + fig = tls.make_subplots(rows=2, insets=[{'cell': (1, 1), 'l': 0.8}, + {'cell': (2, 1), 'l': 0.8}]) assert fig == expected + def test_insets_multiple_bottom_left(): expected = Figure( data=Data(), @@ -1922,8 +1882,8 @@ def test_insets_multiple_bottom_left(): ) fig = tls.make_subplots(rows=2, - insets=[{'cell': (1,1), 'l':0.8}, - {'cell': (2,1), 'l':0.8}], + insets=[{'cell': (1, 1), 'l': 0.8}, + {'cell': (2, 1), 'l': 0.8}], start_cell='bottom-left') assert fig == expected diff --git a/plotly/tests/test_core/test_tools/test_validate.py b/plotly/tests/test_core/test_tools/test_validate.py index 7b88fdd535d..d1b0dc25796 100644 --- a/plotly/tests/test_core/test_tools/test_validate.py +++ b/plotly/tests/test_core/test_tools/test_validate.py @@ -1,8 +1,9 @@ from __future__ import absolute_import -import plotly.tools as tls from nose.tools import raises + from plotly.exceptions import PlotlyError +import plotly.tools as tls def test_validate_valid_fig(): diff --git a/plotly/tests/test_core/test_utils/__init__.py b/plotly/tests/test_core/test_utils/__init__.py index dbd5b79d852..f367e6011a3 100644 --- a/plotly/tests/test_core/test_utils/__init__.py +++ b/plotly/tests/test_core/test_utils/__init__.py @@ -1,3 +1,4 @@ +import warnings + def setup_package(): - import warnings warnings.filterwarnings('ignore') diff --git a/plotly/tests/test_core/test_utils/test_utils.py b/plotly/tests/test_core/test_utils/test_utils.py index 94be40b3949..d894e9e5544 100644 --- a/plotly/tests/test_core/test_utils/test_utils.py +++ b/plotly/tests/test_core/test_utils/test_utils.py @@ -1,13 +1,10 @@ -import sys +from __future__ import absolute_import + +import json from unittest import TestCase from plotly.utils import PlotlyJSONEncoder -if sys.version[:3] == '2.6': - import simplejson as json -else: - import json - class TestJSONEncoder(TestCase): diff --git a/plotly/tests/test_optional/optional_utils.py b/plotly/tests/test_optional/optional_utils.py index b85c86a1732..c31507bd47f 100644 --- a/plotly/tests/test_optional/optional_utils.py +++ b/plotly/tests/test_optional/optional_utils.py @@ -4,7 +4,6 @@ # Force matplotlib to not use any Xwindows backend. matplotlib.use('Agg') from plotly.matplotlylib import Exporter, PlotlyRenderer -from plotly.tests.utils import * def run_fig(fig): diff --git a/plotly/tests/test_optional/test_graph_objs/test_to_dataframe.py b/plotly/tests/test_optional/test_graph_objs/test_to_dataframe.py index a04bd5e6588..a789fe5805a 100644 --- a/plotly/tests/test_optional/test_graph_objs/test_to_dataframe.py +++ b/plotly/tests/test_optional/test_graph_objs/test_to_dataframe.py @@ -2,7 +2,8 @@ from unittest import TestCase -from plotly.graph_objs import * +from plotly.graph_objs import (Data, Figure, Layout, Line, Margin, Marker, + Scatter, XAxis, YAxis) class TestToDataframe(TestCase): diff --git a/plotly/tests/test_optional/test_ipython/test_embed.py b/plotly/tests/test_optional/test_ipython/test_embed.py deleted file mode 100644 index f9a69527828..00000000000 --- a/plotly/tests/test_optional/test_ipython/test_embed.py +++ /dev/null @@ -1,64 +0,0 @@ -from __future__ import absolute_import - -import plotly.tools as tls -import imghdr -import threading -import six -import unittest -version = six.sys.version_info[:2] # need this for conditional testing - -# unittest `skipIf` not supported in 2.6 and IPython not supported in 2.6/3.2 -if version < (2, 7) or (2, 7) < version < (3, 3): - pass -else: - from unittest import skip - - @skip - class TestPlotlyDisplay(unittest.TestCase): - - def setUp(self): - plot_info = {"un": "PlotlyImageTest", "fid": "2"} - url = "https://plot.ly/~{un}/{fid}".format(**plot_info) - self.display_obj = tls.embed(url) - self.results = {} - self.images = {} - self.threads = [] - self.format_to_func = { - "jpeg": self.jpeg_worker, - "png": self.png_worker, - "svg": self.svg_worker, - "pdf": self.pdf_worker} - - def test_plotly_display(self): - for f_format, func in self.format_to_func.items(): - self.threads += [threading.Thread(target=func)] - self.threads[-1].setDaemon(True) - self.threads[-1].start() - for thread in self.threads: - thread.join() - for f_format in self.format_to_func: - result = self.results.get(f_format, False) - print("{f_format}: {result}".format(f_format=f_format, - result=result)) - print("{image}\n".format(image=self.images[f_format][:72])) - assert self.results.get(f_format) - - def jpeg_worker(self): - self.images['jpeg'] = self.display_obj._repr_jpeg_() - if imghdr.what('', self.images['jpeg']) == "jpeg": - self.results["jpeg"] = True - - def png_worker(self): - self.images['png'] = self.display_obj._repr_png_() - if imghdr.what('', self.images['png']) == "png": - self.results["png"] = True - - def svg_worker(self): - self.images['svg'] = self.display_obj._repr_svg_() - if self.images['svg'][:4] == six.b('