-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #658 from plotly/2.0.0
2.0.0
- Loading branch information
Showing
82 changed files
with
8,784 additions
and
6,835 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
from base64 import b64encode | ||
|
||
from requests.compat import builtin_str, is_py2 | ||
|
||
|
||
def _to_native_string(string, encoding): | ||
if isinstance(string, builtin_str): | ||
return string | ||
if is_py2: | ||
return string.encode(encoding) | ||
return string.decode(encoding) | ||
|
||
|
||
def to_native_utf8_string(string): | ||
return _to_native_string(string, 'utf-8') | ||
|
||
|
||
def to_native_ascii_string(string): | ||
return _to_native_string(string, 'ascii') | ||
|
||
|
||
def basic_auth(username, password): | ||
""" | ||
Creates the basic auth value to be used in an authorization header. | ||
This is mostly copied from the requests library. | ||
:param (str) username: A Plotly username. | ||
:param (str) password: The password for the given Plotly username. | ||
:returns: (str) An 'authorization' header for use in a request header. | ||
""" | ||
if isinstance(username, str): | ||
username = username.encode('latin1') | ||
|
||
if isinstance(password, str): | ||
password = password.encode('latin1') | ||
|
||
return 'Basic ' + to_native_ascii_string( | ||
b64encode(b':'.join((username, password))).strip() | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from __future__ import absolute_import | ||
|
||
from plotly.api.v1.clientresp import clientresp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
"""Interface to deprecated /clientresp API. Subject to deletion.""" | ||
from __future__ import absolute_import | ||
|
||
import warnings | ||
|
||
from requests.compat import json as _json | ||
|
||
from plotly import config, utils, version | ||
from plotly.api.v1.utils import request | ||
|
||
|
||
def clientresp(data, **kwargs): | ||
""" | ||
Deprecated endpoint, still used because it can parse data out of a plot. | ||
When we get around to forcing users to create grids and then create plots, | ||
we can finally get rid of this. | ||
:param (list) data: The data array from a figure. | ||
""" | ||
creds = config.get_credentials() | ||
cfg = config.get_config() | ||
|
||
dumps_kwargs = {'sort_keys': True, 'cls': utils.PlotlyJSONEncoder} | ||
|
||
payload = { | ||
'platform': 'python', 'version': version.__version__, | ||
'args': _json.dumps(data, **dumps_kwargs), | ||
'un': creds['username'], 'key': creds['api_key'], 'origin': 'plot', | ||
'kwargs': _json.dumps(kwargs, **dumps_kwargs) | ||
} | ||
|
||
url = '{plotly_domain}/clientresp'.format(**cfg) | ||
response = request('post', url, data=payload) | ||
|
||
# Old functionality, just keeping it around. | ||
parsed_content = response.json() | ||
if parsed_content.get('warning'): | ||
warnings.warn(parsed_content['warning']) | ||
if parsed_content.get('message'): | ||
print(parsed_content['message']) | ||
|
||
return response |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
from __future__ import absolute_import | ||
|
||
import requests | ||
from requests.exceptions import RequestException | ||
|
||
from plotly import config, exceptions | ||
from plotly.api.utils import basic_auth | ||
|
||
|
||
def validate_response(response): | ||
""" | ||
Raise a helpful PlotlyRequestError for failed requests. | ||
:param (requests.Response) response: A Response object from an api request. | ||
:raises: (PlotlyRequestError) If the request failed for any reason. | ||
:returns: (None) | ||
""" | ||
content = response.content | ||
status_code = response.status_code | ||
try: | ||
parsed_content = response.json() | ||
except ValueError: | ||
message = content if content else 'No Content' | ||
raise exceptions.PlotlyRequestError(message, status_code, content) | ||
|
||
message = '' | ||
if isinstance(parsed_content, dict): | ||
error = parsed_content.get('error') | ||
if error: | ||
message = error | ||
else: | ||
if response.ok: | ||
return | ||
if not message: | ||
message = content if content else 'No Content' | ||
|
||
raise exceptions.PlotlyRequestError(message, status_code, content) | ||
|
||
|
||
def get_headers(): | ||
""" | ||
Using session credentials/config, get headers for a v1 API request. | ||
Users may have their own proxy layer and so we free up the `authorization` | ||
header for this purpose (instead adding the user authorization in a new | ||
`plotly-authorization` header). See pull #239. | ||
:returns: (dict) Headers to add to a requests.request call. | ||
""" | ||
headers = {} | ||
creds = config.get_credentials() | ||
proxy_auth = basic_auth(creds['proxy_username'], creds['proxy_password']) | ||
|
||
if config.get_config()['plotly_proxy_authorization']: | ||
headers['authorization'] = proxy_auth | ||
|
||
return headers | ||
|
||
|
||
def request(method, url, **kwargs): | ||
""" | ||
Central place to make any v1 api request. | ||
:param (str) method: The request method ('get', 'put', 'delete', ...). | ||
:param (str) url: The full api url to make the request to. | ||
:param kwargs: These are passed along to requests. | ||
:return: (requests.Response) The response directly from requests. | ||
""" | ||
if kwargs.get('json', None) is not None: | ||
# See plotly.api.v2.utils.request for examples on how to do this. | ||
raise exceptions.PlotlyError('V1 API does not handle arbitrary json.') | ||
kwargs['headers'] = dict(kwargs.get('headers', {}), **get_headers()) | ||
kwargs['verify'] = config.get_config()['plotly_ssl_verification'] | ||
try: | ||
response = requests.request(method, url, **kwargs) | ||
except RequestException as e: | ||
# The message can be an exception. E.g., MaxRetryError. | ||
message = str(getattr(e, 'message', 'No message')) | ||
response = getattr(e, 'response', None) | ||
status_code = response.status_code if response else None | ||
content = response.content if response else 'No content' | ||
raise exceptions.PlotlyRequestError(message, status_code, content) | ||
validate_response(response) | ||
return response |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from __future__ import absolute_import | ||
|
||
from plotly.api.v2 import (files, folders, grids, images, plot_schema, plots, | ||
users) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
"""Interface to Plotly's /v2/files endpoints.""" | ||
from __future__ import absolute_import | ||
|
||
from plotly.api.v2.utils import build_url, make_params, request | ||
|
||
RESOURCE = 'files' | ||
|
||
|
||
def retrieve(fid, share_key=None): | ||
""" | ||
Retrieve a general file from Plotly. | ||
:param (str) fid: The `{username}:{idlocal}` identifier. E.g. `foo:88`. | ||
:param (str) share_key: The secret key granting 'read' access if private. | ||
:returns: (requests.Response) Returns response directly from requests. | ||
""" | ||
url = build_url(RESOURCE, id=fid) | ||
params = make_params(share_key=share_key) | ||
return request('get', url, params=params) | ||
|
||
|
||
def update(fid, body): | ||
""" | ||
Update a general file from Plotly. | ||
:param (str) fid: The `{username}:{idlocal}` identifier. E.g. `foo:88`. | ||
:param (dict) body: A mapping of body param names to values. | ||
:returns: (requests.Response) Returns response directly from requests. | ||
""" | ||
url = build_url(RESOURCE, id=fid) | ||
return request('put', url, json=body) | ||
|
||
|
||
def trash(fid): | ||
""" | ||
Soft-delete a general file from Plotly. (Can be undone with 'restore'). | ||
:param (str) fid: The `{username}:{idlocal}` identifier. E.g. `foo:88`. | ||
:returns: (requests.Response) Returns response directly from requests. | ||
""" | ||
url = build_url(RESOURCE, id=fid, route='trash') | ||
return request('post', url) | ||
|
||
|
||
def restore(fid): | ||
""" | ||
Restore a trashed, general file from Plotly. See 'trash'. | ||
:param (str) fid: The `{username}:{idlocal}` identifier. E.g. `foo:88`. | ||
:returns: (requests.Response) Returns response directly from requests. | ||
""" | ||
url = build_url(RESOURCE, id=fid, route='restore') | ||
return request('post', url) | ||
|
||
|
||
def permanent_delete(fid): | ||
""" | ||
Permanently delete a trashed, general file from Plotly. See 'trash'. | ||
:param (str) fid: The `{username}:{idlocal}` identifier. E.g. `foo:88`. | ||
:returns: (requests.Response) Returns response directly from requests. | ||
""" | ||
url = build_url(RESOURCE, id=fid, route='permanent_delete') | ||
return request('delete', url) | ||
|
||
|
||
def lookup(path, parent=None, user=None, exists=None): | ||
""" | ||
Retrieve a general file from Plotly without needing a fid. | ||
:param (str) path: The '/'-delimited path specifying the file location. | ||
:param (int) parent: Parent id, an integer, which the path is relative to. | ||
:param (str) user: The username to target files for. Defaults to requestor. | ||
:param (bool) exists: If True, don't return the full file, just a flag. | ||
:returns: (requests.Response) Returns response directly from requests. | ||
""" | ||
url = build_url(RESOURCE, route='lookup') | ||
params = make_params(path=path, parent=parent, user=user, exists=exists) | ||
return request('get', url, params=params) |
Oops, something went wrong.