def test_set_config_file(): pd, ps = 'this', 'thing' tls.set_config_file(plotly_domain=pd, plotly_streaming_domain=ps) config = tls.get_config_file() assert config['plotly_domain'] == pd assert config['plotly_streaming_domain'] == ps tls.reset_config_file() # else every would hate me :)
def test_set_config_file_all_entries(self): # Check set_config and get_config return the same values domain, streaming_domain, api, sharing = ('this', 'thing', 'that', 'private') ssl_verify, proxy_auth, world_readable, auto_open = (True, True, False, False) tools.set_config_file(plotly_domain=domain, plotly_streaming_domain=streaming_domain, plotly_api_domain=api, plotly_ssl_verification=ssl_verify, plotly_proxy_authorization=proxy_auth, world_readable=world_readable, auto_open=auto_open) config = tools.get_config_file() self.assertEqual(config['plotly_domain'], domain) self.assertEqual(config['plotly_streaming_domain'], streaming_domain) self.assertEqual(config['plotly_api_domain'], api) self.assertEqual(config['plotly_ssl_verification'], ssl_verify) self.assertEqual(config['plotly_proxy_authorization'], proxy_auth) self.assertEqual(config['world_readable'], world_readable) self.assertEqual(config['sharing'], sharing) self.assertEqual(config['auto_open'], auto_open) tools.reset_config_file()
def get_config(): """Returns either module config or file config.""" config = tools.get_config_file() for config_key in config: if _config.get(config_key): config[config_key] = _config[config_key] return config
def get_config(): """Returns either module config or file config.""" config = tools.get_config_file() for config_key in config: if _config.get(config_key) is not None: config[config_key] = _config[config_key] return config
def test_reset_config_file(self): # Check reset_config and get_config return the same values tools.reset_config_file() config = tools.get_config_file() self.assertEqual(config['plotly_domain'], 'https://plot.ly') self.assertEqual(config['plotly_streaming_domain'], 'stream.plot.ly')
def get_config(): """Returns either module config or file config.""" config = tools.get_config_file() session_config = get_session_config() for config_key in config: # checking for not false, but truthy value here is the desired behavior session_value = session_config.get(config_key) if session_value is False or session_value: config[config_key] = session_value return config
def test_set_config_file_two_entries(self): # Check set_config and get_config given only two entries return the # same values domain, streaming_domain = 'this', 'thing' tools.set_config_file(plotly_domain=domain, plotly_streaming_domain=streaming_domain) config = tools.get_config_file() self.assertEqual(config['plotly_domain'], domain) self.assertEqual(config['plotly_streaming_domain'], streaming_domain) tools.reset_config_file()
def test_set_config_updates_plot_options(self): original_config = tls.get_config_file() new_options = { 'world_readable': not original_config['world_readable'], 'auto_open': not original_config['auto_open'], 'sharing': ('public' if original_config['world_readable'] is False else 'secret') } tls.set_config_file(**new_options) options = py._plot_option_logic({}) for key in new_options: self.assertEqual(new_options[key], options[key])
def test_set_config_file(): pd, ps = 'this', 'thing' ssl_verify, proxy_auth = True, True tls.set_config_file(plotly_domain=pd, plotly_streaming_domain=ps, plotly_ssl_verification=ssl_verify, plotly_proxy_authorization=proxy_auth) config = tls.get_config_file() assert config['plotly_domain'] == pd assert config['plotly_streaming_domain'] == ps assert config['plotly_ssl_verification'] == ssl_verify assert config['plotly_proxy_authorization'] == proxy_auth tls.reset_config_file() # else every would hate me :)
def open(self): """Open streaming connection to plotly. For more help, see: `help(plotly.plotly.Stream)` or see examples and tutorials here: http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb """ streaming_url = tools.get_config_file()['plotly_streaming_domain'] self._stream = chunked_requests.Stream(streaming_url, 80, {'Host': streaming_url, 'plotly-streamtoken': self.stream_id})
def _send_to_plotly(figure, **plot_options): """ """ fig = tools._replace_newline(figure) # does not mutate figure data = json.dumps(fig['data'] if 'data' in fig else [], cls=utils._plotlyJSONEncoder) file_credentials = tools.get_credentials_file() if ('username' in _credentials) and ('api_key' in _credentials): username, api_key = _credentials['username'], _credentials['api_key'] elif ('username' in file_credentials) and ('api_key' in file_credentials): (username, api_key) = (file_credentials['username'], file_credentials['api_key']) else: raise exceptions.PlotlyLocalCredentialsError() kwargs = json.dumps(dict(filename=plot_options['filename'], fileopt=plot_options['fileopt'], world_readable=plot_options['world_readable'], layout=fig['layout'] if 'layout' in fig else {}), cls=utils._plotlyJSONEncoder) payload = dict(platform='python', # TODO: It'd be cool to expose the platform for RaspPi and others version=version.__version__, args=data, un=username, key=api_key, origin='plot', kwargs=kwargs) url = tools.get_config_file()['plotly_domain'] + "/clientresp" r = requests.post(url, data=payload) r.raise_for_status() r = json.loads(r.text) if 'error' in r and r['error'] != '': print((r['error'])) if 'warning' in r and r['warning'] != '': warnings.warn(r['warning']) if 'message' in r and r['message'] != '': print((r['message'])) return r
def _send_to_plotly(figure, **plot_options): """ """ fig = tools._replace_newline(figure) # does not mutate figure data = json.dumps(fig['data'] if 'data' in fig else [], cls=utils._plotlyJSONEncoder) file_credentials = tools.get_credentials_file() if ('username' in _credentials) and ('api_key' in _credentials): username, api_key = _credentials['username'], _credentials['api_key'] elif ('username' in file_credentials) and ('api_key' in file_credentials): (username, api_key) = (file_credentials['username'], file_credentials['api_key']) else: raise exceptions.PlotlyLocalCredentialsError() kwargs = json.dumps(dict(filename=plot_options['filename'], fileopt=plot_options['fileopt'], world_readable=plot_options['world_readable'], layout=fig['layout'] if 'layout' in fig else {}), cls=utils._plotlyJSONEncoder) payload = dict( platform= 'python', # TODO: It'd be cool to expose the platform for RaspPi and others version=version.__version__, args=data, un=username, key=api_key, origin='plot', kwargs=kwargs) url = tools.get_config_file()['plotly_domain'] + "/clientresp" r = requests.post(url, data=payload) r.raise_for_status() r = json.loads(r.text) if 'error' in r and r['error'] != '': print((r['error'])) if 'warning' in r and r['warning'] != '': warnings.warn(r['warning']) if 'message' in r and r['message'] != '': print((r['message'])) return r
def test_set_config_file_all_entries(self): # Check set_config and get_config return the same values domain, streaming_domain, api = 'this', 'thing', 'that' ssl_verify, proxy_auth, readable = True, True, True tools.set_config_file(plotly_domain=domain, plotly_streaming_domain=streaming_domain, plotly_api_domain=api, plotly_ssl_verification=ssl_verify, plotly_proxy_authorization=proxy_auth, world_readable=readable) config = tools.get_config_file() self.assertEqual(config['plotly_domain'], domain) self.assertEqual(config['plotly_streaming_domain'], streaming_domain) self.assertEqual(config['plotly_api_domain'], api) self.assertEqual(config['plotly_ssl_verification'], ssl_verify) self.assertEqual(config['plotly_proxy_authorization'], proxy_auth) self.assertEqual(config['world_readable'], readable) tools.reset_config_file()
def get_figure(file_owner_or_url, file_id=None, raw=False): """Returns a JSON figure representation for the specified file Plotly uniquely identifies figures with a 'file_owner'/'file_id' pair. Since each file is given a corresponding unique url, you may also simply pass a valid plotly url as the first argument. Note, if you're using a file_owner string as the first argument, you MUST specify a `file_id` keyword argument. Else, if you're using a url string as the first argument, you MUST NOT specify a `file_id` keyword argument, or file_id must be set to Python's None value. Positional arguments: file_owner_or_url (string) -- a valid plotly username OR a valid plotly url Keyword arguments: file_id (default=None) -- an int or string that can be converted to int if you're using a url, don't fill this in! raw (default=False) -- if true, return unicode JSON string verbatim** **by default, plotly will return a Figure object (run help(plotly .graph_objs.Figure)). This representation decodes the keys and values from unicode (if possible), removes information irrelevant to the figure representation, and converts the JSON dictionary objects to plotly `graph objects`. """ plotly_rest_url = tools.get_config_file()['plotly_domain'] if file_id is None: # assume we're using a url url = file_owner_or_url if url[:len(plotly_rest_url)] != plotly_rest_url: raise exceptions.PlotlyError( "Because you didn't supply a 'file_id' in the call, " "we're assuming you're trying to snag a figure from a url. " "You supplied the url, '{0}', we expected it to start with " "'{1}'." "\nRun help on this function for more information." "".format(url, plotly_rest_url)) head = plotly_rest_url + "/~" file_owner = url.replace(head, "").split('/')[0] file_id = url.replace(head, "").split('/')[1] else: file_owner = file_owner_or_url resource = "/apigetfile/{username}/{file_id}".format(username=file_owner, file_id=file_id) (username, api_key) = _validation_key_logic() headers = { 'plotly-username': username, 'plotly-apikey': api_key, 'plotly-version': version.__version__, 'plotly-platform': 'python' } try: test_if_int = int(file_id) except ValueError: raise exceptions.PlotlyError( "The 'file_id' argument was not able to be converted into an " "integer number. Make sure that the positional 'file_id' argument " "is a number that can be converted into an integer or a string " "that can be converted into an integer.") if int(file_id) < 0: raise exceptions.PlotlyError( "The 'file_id' argument must be a non-negative number.") response = requests.get(plotly_rest_url + resource, headers=headers) if response.status_code == 200: if six.PY3: content = json.loads(response.content.decode('unicode_escape')) else: content = json.loads(response.content) response_payload = content['payload'] figure = response_payload['figure'] utils.decode_unicode(figure) if raw: return figure else: return tools.get_valid_graph_obj(figure, obj_type='Figure') else: try: content = json.loads(response.content) raise exceptions.PlotlyError(content) except: raise exceptions.PlotlyError( "There was an error retrieving this file")
def test_default_options(self): options = py._plot_option_logic({}) config_options = tls.get_config_file() for key in options: if key != 'fileopt' and key in config_options: self.assertEqual(options[key], config_options[key])
class Stream: """ Interface to Plotly's real-time graphing API. Initialize a Stream object with a stream_id found in {plotly_domain}/settings. Real-time graphs are initialized with a call to `plot` that embeds your unique `stream_id`s in each of the graph's traces. The `Stream` interface plots data to these traces, as identified with the unique stream_id, in real-time. Every viewer of the graph sees the same data at the same time. View examples and tutorials here: http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb Stream example: # Initialize a streaming graph # by embedding stream_id's in the graph's traces >>> stream_id = "your_stream_id" # See {plotly_domain}/settings >>> py.plot(Data([Scatter(x=[], y=[], stream=dict(token=stream_id, maxpoints=100))]) # Stream data to the import trace >>> stream = Stream(stream_id) # Initialize a stream object >>> stream.open() # Open the stream >>> stream.write(dict(x=1, y=1)) # Plot (1, 1) in your graph """ @utils.template_doc(**tools.get_config_file()) def __init__(self, stream_id): """ Initialize a Stream object with your unique stream_id. Find your stream_id at {plotly_domain}/settings. For more help, see: `help(plotly.plotly.Stream)` or see examples and tutorials here: http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb """ self.stream_id = stream_id self.connected = False def open(self): """Open streaming connection to plotly. For more help, see: `help(plotly.plotly.Stream)` or see examples and tutorials here: http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb """ streaming_url = get_config()['plotly_streaming_domain'] self._stream = chunked_requests.Stream(streaming_url, 80, {'Host': streaming_url, 'plotly-streamtoken': self.stream_id}) def write(self, trace, layout=None, validate=True, reconnect_on=(200, '', 408)): """Write to an open stream. Once you've instantiated a 'Stream' object with a 'stream_id', you can 'write' to it in real time. positional arguments: trace - A valid plotly trace object (e.g., Scatter, Heatmap, etc.). Not all keys in these are `stremable` run help(Obj) on the type of trace your trying to stream, for each valid key, if the key is streamable, it will say 'streamable = True'. Trace objects must be dictionary-like. keyword arguments: layout (default=None) - A valid Layout object Run help(plotly.graph_objs.Layout) validate (default = True) - Validate this stream before sending? This will catch local errors if set to True. Some valid keys for trace dictionaries: 'x', 'y', 'text', 'z', 'marker', 'line' Examples: >>> write(dict(x=1, y=2)) # assumes 'scatter' type >>> write(Bar(x=[1, 2, 3], y=[10, 20, 30])) >>> write(Scatter(x=1, y=2, text='scatter text')) >>> write(Scatter(x=1, y=3, marker=Marker(color='blue'))) >>> write(Heatmap(z=[[1, 2, 3], [4, 5, 6]])) The connection to plotly's servers is checked before writing and reconnected if disconnected and if the response status code is in `reconnect_on`. For more help, see: `help(plotly.plotly.Stream)` or see examples and tutorials here: http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb """ stream_object = dict() stream_object.update(trace) if 'type' not in stream_object: stream_object['type'] = 'scatter' if validate: try: tools.validate(stream_object, stream_object['type']) except exceptions.PlotlyError as err: raise exceptions.PlotlyError( "Part of the data object with type, '{0}', is invalid. " "This will default to 'scatter' if you do not supply a " "'type'. If you do not want to validate your data objects " "when streaming, you can set 'validate=False' in the call " "to 'your_stream.write()'. Here's why the object is " "invalid:\n\n{1}".format(stream_object['type'], err) ) try: tools.validate_stream(stream_object, stream_object['type']) except exceptions.PlotlyError as err: raise exceptions.PlotlyError( "Part of the data object with type, '{0}', cannot yet be " "streamed into Plotly. If you do not want to validate your " "data objects when streaming, you can set 'validate=False' " "in the call to 'your_stream.write()'. Here's why the " "object cannot be streamed:\n\n{1}" "".format(stream_object['type'], err) ) if layout is not None: try: tools.validate(layout, 'Layout') except exceptions.PlotlyError as err: raise exceptions.PlotlyError( "Your layout kwarg was invalid. " "Here's why:\n\n{0}".format(err) ) del stream_object['type'] if layout is not None: stream_object.update(dict(layout=layout)) # TODO: allow string version of this? jdata = json.dumps(stream_object, cls=utils._plotlyJSONEncoder) jdata += "\n" try: self._stream.write(jdata, reconnect_on=reconnect_on) except AttributeError: raise exceptions.PlotlyError("Stream has not been opened yet, " "cannot write to a closed connection. " "Call `open()` on the stream to open the stream.") def close(self): """ Close the stream connection to plotly's streaming servers. For more help, see: `help(plotly.plotly.Stream)` or see examples and tutorials here: http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb """ try: self._stream.close() except AttributeError: raise exceptions.PlotlyError("Stream has not been opened yet.")
figure = response_payload['figure'] utils.decode_unicode(figure) if raw: return figure else: return tools.get_valid_graph_obj(figure, obj_type='Figure') else: try: content = json.loads(response.content) raise exceptions.PlotlyError(content) except: raise exceptions.PlotlyError( "There was an error retrieving this file") @utils.template_doc(**tools.get_config_file()) class Stream: """ Interface to Plotly's real-time graphing API. Initialize a Stream object with a stream_id found in {plotly_domain}/settings. Real-time graphs are initialized with a call to `plot` that embeds your unique `stream_id`s in each of the graph's traces. The `Stream` interface plots data to these traces, as identified with the unique stream_id, in real-time. Every viewer of the graph sees the same data at the same time. View examples and tutorials here: http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb Stream example:
def get_figure(file_owner_or_url, file_id=None, raw=False): """Returns a JSON figure representation for the specified file Plotly uniquely identifies figures with a 'file_owner'/'file_id' pair. Since each file is given a corresponding unique url, you may also simply pass a valid plotly url as the first argument. Note, if you're using a file_owner string as the first argument, you MUST specify a `file_id` keyword argument. Else, if you're using a url string as the first argument, you MUST NOT specify a `file_id` keyword argument, or file_id must be set to Python's None value. Positional arguments: file_owner_or_url (string) -- a valid plotly username OR a valid plotly url Keyword arguments: file_id (default=None) -- an int or string that can be converted to int if you're using a url, don't fill this in! raw (default=False) -- if true, return unicode JSON string verbatim** **by default, plotly will return a Figure object (run help(plotly .graph_objs.Figure)). This representation decodes the keys and values from unicode (if possible), removes information irrelevant to the figure representation, and converts the JSON dictionary objects to plotly `graph objects`. """ plotly_rest_url = tools.get_config_file()['plotly_domain'] if file_id is None: # assume we're using a url url = file_owner_or_url if url[:len(plotly_rest_url)] != plotly_rest_url: raise exceptions.PlotlyError( "Because you didn't supply a 'file_id' in the call, " "we're assuming you're trying to snag a figure from a url. " "You supplied the url, '{0}', we expected it to start with " "'{1}'." "\nRun help on this function for more information." "".format(url, plotly_rest_url)) head = plotly_rest_url + "/~" file_owner = url.replace(head, "").split('/')[0] file_id = url.replace(head, "").split('/')[1] else: file_owner = file_owner_or_url resource = "/apigetfile/{username}/{file_id}".format(username=file_owner, file_id=file_id) (username, api_key) = _validation_key_logic() headers = {'plotly-username': username, 'plotly-apikey': api_key, 'plotly-version': version.__version__, 'plotly-platform': 'python'} try: test_if_int = int(file_id) except ValueError: raise exceptions.PlotlyError( "The 'file_id' argument was not able to be converted into an " "integer number. Make sure that the positional 'file_id' argument " "is a number that can be converted into an integer or a string " "that can be converted into an integer." ) if int(file_id) < 0: raise exceptions.PlotlyError( "The 'file_id' argument must be a non-negative number." ) response = requests.get(plotly_rest_url + resource, headers=headers) if response.status_code == 200: if six.PY3: content = json.loads(response.content.decode('unicode_escape')) else: content = json.loads(response.content) response_payload = content['payload'] figure = response_payload['figure'] utils.decode_unicode(figure) if raw: return figure else: return tools.get_valid_graph_obj(figure, obj_type='Figure') else: try: content = json.loads(response.content) raise exceptions.PlotlyError(content) except: raise exceptions.PlotlyError( "There was an error retrieving this file")
def get(figure_or_data, format='png', width=None, height=None): """ Return a static image of the plot described by `figure`. Valid formats: 'png', 'svg', 'jpeg', 'pdf' """ if isinstance(figure_or_data, dict): figure = figure_or_data elif isinstance(figure_or_data, list): figure = {'data': figure_or_data} if format not in ['png', 'svg', 'jpeg', 'pdf']: raise exceptions.PlotlyError("Invalid format. " "This version of your Plotly-Python " "package currently only supports " "png, svg, jpeg, and pdf. " "Learn more about image exporting, " "and the currently supported file " "types here: " "https://plot.ly/python/static-image-export/") (username, api_key) = _validation_key_logic() headers = {'plotly-username': username, 'plotly-apikey': api_key, 'plotly-version': version.__version__, 'plotly-platform': 'python'} payload = { 'figure': figure, 'format': format } if width is not None: payload['width'] = width if height is not None: payload['height'] = height url = tools.get_config_file()['plotly_domain'] + "/apigenimage/" res = requests.post(url, data=json.dumps(payload, cls=utils._plotlyJSONEncoder), headers=headers) headers = res.headers if res.status_code == 200: if ('content-type' in headers and headers['content-type'] in ['image/png', 'image/jpeg', 'application/pdf', 'image/svg+xml']): return res.content elif ('content-type' in headers and 'json' in headers['content-type']): return_data = json.loads(res.content) return return_data['image'] else: try: if ('content-type' in headers and 'json' in headers['content-type']): return_data = json.loads(res.content) else: return_data = {'error': res.content} except: raise exceptions.PlotlyError("The response " "from plotly could " "not be translated.") raise exceptions.PlotlyError(return_data['error'])
def get(figure_or_data, format='png', width=None, height=None): """ Return a static image of the plot described by `figure`. Valid formats: 'png', 'svg', 'jpeg', 'pdf' """ if isinstance(figure_or_data, dict): figure = figure_or_data elif isinstance(figure_or_data, list): figure = {'data': figure_or_data} if format not in ['png', 'svg', 'jpeg', 'pdf']: raise exceptions.PlotlyError( "Invalid format. " "This version of your Plotly-Python " "package currently only supports " "png, svg, jpeg, and pdf. " "Learn more about image exporting, " "and the currently supported file " "types here: " "https://plot.ly/python/static-image-export/") (username, api_key) = _validation_key_logic() headers = { 'plotly-username': username, 'plotly-apikey': api_key, 'plotly-version': version.__version__, 'plotly-platform': 'python' } payload = {'figure': figure, 'format': format} if width is not None: payload['width'] = width if height is not None: payload['height'] = height url = tools.get_config_file()['plotly_domain'] + "/apigenimage/" res = requests.post(url, data=json.dumps(payload, cls=utils._plotlyJSONEncoder), headers=headers) headers = res.headers if res.status_code == 200: if ('content-type' in headers and headers['content-type'] in [ 'image/png', 'image/jpeg', 'application/pdf', 'image/svg+xml' ]): return res.content elif ('content-type' in headers and 'json' in headers['content-type']): return_data = json.loads(res.content) return return_data['image'] else: try: if ('content-type' in headers and 'json' in headers['content-type']): return_data = json.loads(res.content) else: return_data = {'error': res.content} except: raise exceptions.PlotlyError("The response " "from plotly could " "not be translated.") raise exceptions.PlotlyError(return_data['error'])
def test_reset_config_file(): tls.reset_config_file() config = tls.get_config_file() assert config['plotly_domain'] == 'https://plot.ly' assert config['plotly_streaming_domain'] == 'stream.plot.ly'