10000 First crack at `resources`. · yuan3y/plotly.py@aa8f7e4 · GitHub
[go: up one dir, main page]

Skip to content

Commit aa8f7e4

Browse files
committed
First crack at resources.
1 parent 095b9da commit aa8f7e4

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

plotly/plotly/resources.py

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
"""
2+
A module wrapping the Plotly API's REST resources.
3+
4+
"""
5+
from __future__ import absolute_import
6+
7+
import base64
8+
import json
9+
10+
import requests
11+
import six
12+
13+
from plotly.version import __version__
14+
15+
api_domain = 'api.plot.ly'
16+
api_version = 'v2'
17+
18+
19+
class BaseResource(object):
20+
21+
base_name = None
22+
resource = None
23+
24+
def get_url(self, api_path, version='v2', **params):
25+
schema = 'https'
26+
str_params = {str(k): str(v) for k, v in params.items()}
27+
q = '&'.join('='.join(item) for item in str_params.items())
28+
d = {'schema': schema, 'domain': api_domain, 'version': version,
29+
'api_path': api_path, 'q': q}
30+
if q:
31+
return '{schema}://{domain}/{version}/{api_path}?{q}'.format(**d)
32+
else:
33+
return '{schema}://{domain}/{version}/{api_path}'.format(**d)
34+
35+
def get_headers(self):
36+
# TODO: fix circular import
37+
from plotly.plotly.plotly import get_credentials, get_config
38+
credentials = get_credentials()
39+
40+
# TODO: validate here?
41+
username, api_key = credentials['username'], credentials['api_key']
42+
encoded_api_auth = base64.b64encode(six.b('{0}:{1}'.format(
43+
username, api_key))).decode('utf8')
44+
45+
header_dict = {
46+
'plotly-client-platform': 'python {0}'.format(__version__)
47+
}
48+
49+
if get_config()['plotly_proxy_authorization']:
50+
proxy_username = credentials['proxy_username']
51+
proxy_password = credentials['proxy_password']
52+
encoded_proxy_auth = base64.b64encode(six.b('{0}:{1}'.format(
53+
proxy_username, proxy_password))).decode('utf8')
54+
header_dict['authorization'] = 'Basic ' + encoded_proxy_auth
55+
header_dict['plotly-authorization'] = 'Basic ' + encoded_api_auth
56+
else:
57+
header_dict['authorization'] = 'Basic ' + encoded_api_auth
58+
59+
return header_dict
60+
61+
def request(self, method, url, data=None):
62+
request_dict = {
63+
'headers': self.get_headers()
64+
}
65+
if data is not None:
66+
request_dict['data'] = data
67+
68+
response = requests.request(method, url, **request_dict)
69+
response.raise_for_status()
70+
return response
71+
72+
def get_response_data(self, method, url, data=None):
73+
response = self.request(method, url, data=data)
74+
if six.PY3:
75+
content = str(response.content, encoding='utf-8')
76+
else:
77+
content = response.content
78+
data = json.loads(content)
79+
80+
if 'file' in data:
81+
return data['file'] # Create requests are enveloped.
82+
else:
83+
return data
84+
85+
def get_create_url(self, version='v2', **params):
86+
api_path = '{}'.format(self.base_name)
87+
return self.get_url(api_path, version=version, **params)
88+
89+
def get_detail_url(self, fid, version='v2', **params):
90+
api_path = '{}/{}'.format(self.base_name, fid)
91+
return self.get_url(api_path, version=version, **params)
92+
93+
def get_trash_url(self, fid, version='v2', **params):
94+
api_path = '{}/{}/trash'.format(self.base_name, fid)
95+
return self.get_url(api_path, version=version, **params)
96+
97+
def get_restore_url(self, fid, version='v2', **params):
98+
api_path = '{}/{}/restore'.format(self.base_name, fid)
99+
return self.get_url(api_path, version=version, **params)
100+
101+
def get_permanent_delete_url(self, fid, version='v2', **params):
102+
api_path = '{}/{}/permanent_delete'.format(self.base_name, fid)
103+
return self.get_url(api_path, version=version, **params)
104+
105+
106+
class FileResource(BaseResource):
107+
108+
base_name = 'files'
109+
fid = None
110+
111+
def __init__(self, fid=None, data=None):
112+
if fid is not None and data is not None:
113+
raise Exception('TBD')
114+
115+
if fid is not None:
116+
self.fid = fid
117+
self.retrieve()
118+
elif data is not None:
119+
self.create(data=data)
120+
121+
def create(self, data):
122+
"""Standard CRUD 'create'."""
123+
url = self.get_create_url()
124+
self.resource = self.get_response_data('post', url, data=data)
125+
self.fid = self.resource['fid']
126+
return self.resource
127+
128+
def retrieve(self):
129+
"""Standard CRUD 'retrieve'."""
130+
url = self.get_detail_url(self.fid)
131+
self.resource = self.get_response_data('get', url)
132+
return self.resource
133+
134+
def update(self):
135+
"""Similar to CRUD 'update'."""
136+
url = self.get_detail_url(self.fid)
137+
self.resource = self.get_response_data('put', url)
138+
return self.resource
139+
140+
def permanent_delete(self):
141+
"""Similar to CRUD 'destroy'."""
142+
url = self.get_permanent_delete_url(self.fid)
143+
144+
# TODO: how should non-object returns work?
145+
self.request('delete', url)
146+
self.resource = None
147+
return self.resource
148+
149+
def trash(self):
150+
"""Before destroying a resource, you need to trash it."""
151+
url = self.get_trash_url(self.fid)
152+
self.resource = self.get_response_data('post', url)
153+
return self.resource
154+
155+
def patch(self, data):
156+
"""Partial update on resource."""
157+
url = self.get_detail_url(self.fid)
158+
self.resource = self.get_response_data('patch', url, data=data)
159+
return self.resource
160+
161+
162+
class PlotResource(FileResource):
163+
pass
164+
165+
166+
class GridResource(FileResource):
167+
pass
168+
169+
170+
class FolderResource(FileResource):
171+
pass

0 commit comments

Comments
 (0)
0