Skip to content

Commit 4e644af

Browse files
committed
Merge pull request #284 from plotly/cache-plot-schema
Download and cache plot schema (or always download if no file permissions).
2 parents 2a22483 + fe66f9c commit 4e644af

File tree

9 files changed

+14896
-82
lines changed

9 files changed

+14896
-82
lines changed

make_instructions.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Available targets (i.e. $ make target):
1818

1919
readme -> `less` this file
2020

21+
update_default_schema -> download the latest plot schema from plot.ly
22+
2123
setup_subs -> delete old submodule locations, init, update, and sync new
2224

2325
install -> 1. sync submodules 2. install plotly with setup.py

makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ setup_subs :
1717
git submodule update
1818
make sync_subs
1919

20+
update_default_schema :
21+
@echo "Making sure the default-schema.json file is up to date"
22+
python -c "import json;\
23+
from plotly.graph_reference import GRAPH_REFERENCE;\
24+
f = open('plotly/graph_reference/default-schema.json', 'w');\
25+
json.dump(GRAPH_REFERENCE, f, indent=4, sort_keys=True,\
26+
separators=(',', ': '));\
27+
f.close()"
28+
2029
install : sync_subs
2130
@echo ""
2231
@echo "Installing Python API with make"

plotly/files.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import os
2+
3+
# file structure
4+
PLOTLY_DIR = os.path.join(os.path.expanduser("~"), ".plotly")
5+
CREDENTIALS_FILE = os.path.join(PLOTLY_DIR, ".credentials")
6+
CONFIG_FILE = os.path.join(PLOTLY_DIR, ".config")
7+
GRAPH_REFERENCE_FILE = os.path.join(PLOTLY_DIR, ".graph_reference")
8+
TEST_DIR = os.path.join(os.path.expanduser("~"), ".test")
9+
TEST_FILE = os.path.join(PLOTLY_DIR, ".permission_test")
10+
11+
# this sets both the DEFAULTS and the TYPES for these files
12+
FILE_CONTENT = {CREDENTIALS_FILE: {'username': '',
13+
'api_key': '',
14+
'proxy_username': '',
15+
'proxy_password': '',
16+
'stream_ids': []},
17+
CONFIG_FILE: {'plotly_domain': 'https://plot.ly',
18+
'plotly_streaming_domain': 'stream.plot.ly',
19+
'plotly_api_domain': 'https://api.plot.ly',
20+
'plotly_ssl_verification': True,
21+
'plotly_proxy_authorization': False,
22+
'world_readable': True}}
23+
24+
try:
25+
os.mkdir(TEST_DIR)
26+
os.rmdir(TEST_DIR)
27+
if not os.path.exists(PLOTLY_DIR):
28+
os.mkdir(PLOTLY_DIR)
29+
f = open(TEST_FILE, 'w')
30+
f.write('testing\n')
31+
f.close()
32+
os.remove(TEST_FILE)
33+
_file_permissions = True
34+
except:
35+
_file_permissions = False
36+
37+
38+
def check_file_permissions():
39+
return _file_permissions

plotly/graph_reference.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
This module handles accessing, storing, and managing the graph reference.
3+
4+
"""
5+
from __future__ import absolute_import
6+
7+
import hashlib
8+
import json
9+
import os
10+
import requests
11+
from pkg_resources import resource_string
12+
13+
import six
14+
15+
from plotly import exceptions, files, utils
16+
17+
GRAPH_REFERENCE_PATH = '/v2/plot-schema'
18+
GRAPH_REFERENCE_DOWNLOAD_TIMEOUT = 5 # seconds
19+
20+
21+
def get_graph_reference():
22+
"""
23+
Attempts to load local copy of graph reference or makes GET request if DNE.
24+
25+
:return: (dict) The graph reference.
26+
:raises: (PlotlyError) When graph reference DNE and GET request fails.
27+
28+
"""
29+
default_config = files.FILE_CONTENT[files.CONFIG_FILE]
30+
if files.check_file_permissions():
31+
graph_reference = utils.load_json_dict(files.GRAPH_REFERENCE_FILE)
32+
config = utils.load_json_dict(files.CONFIG_FILE)
33+
34+
# TODO: https://github.com/plotly/python-api/issues/293
35+
plotly_api_domain = config.get('plotly_api_domain',
36+
default_config['plotly_api_domain'])
37+
else:
38+
graph_reference = {}
39+
plotly_api_domain = default_config['plotly_api_domain']
40+
41+
sha1 = hashlib.sha1(six.b(str(graph_reference))).hexdigest()
42+
43+
graph_reference_url = '{}{}?sha1={}'.format(plotly_api_domain,
44+
GRAPH_REFERENCE_PATH, sha1)
45+
46+
try:
47+
response = requests.get(graph_reference_url,
48+
timeout=GRAPH_REFERENCE_DOWNLOAD_TIMEOUT)
49+
response.raise_for_status()
50+
except requests.exceptions.RequestException:
51+
if not graph_reference:
52+
path = os.path.join('graph_reference', 'default-schema.json')
53+
s = resource_string('plotly', path).decode('utf-8')
54+
graph_reference = json.loads(s)
55+
else:
56+
if six.PY3:
57+
content = str(response.content, encoding='utf-8')
58+
else:
59+
content = response.content
60+
data = json.loads(content)
61+
if data['modified']:
62+
graph_reference = data['schema']
63+
64+
return utils.decode_unicode(graph_reference)
65+
66+
GRAPH_REFERENCE = get_graph_reference()

0 commit comments

Comments
 (0)