Skip to content

Commit 7c1adde

Browse files
authored
Merge pull request #739 from plotly/presentations-wrapper
Presentations wrapper
2 parents a611f4c + f9424c2 commit 7c1adde

File tree

12 files changed

+1683
-10
lines changed

12 files changed

+1683
-10
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

5+
## [2.2.0] - 2017-10-20
6+
### Added
7+
- NEW Presentations API for Python! Run `help(plotly.presentation_objs.Presentations)` for help or check out the new [documentation](https://plot.ly/python/presentations-api/)
8+
59
## [2.1.0] - 2017-10-10
610
### Updated
711
- Updated `plotly.min.js` to version 1.31.0.

plotly/api/v2/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from __future__ import absolute_import
22

33
from plotly.api.v2 import (dash_apps, dashboards, files, folders, grids,
4-
images, plot_schema, plots, users)
4+
images, plot_schema, plots, spectacle_presentations,
5+
users)
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""
2+
Interface to Plotly's /v2/spectacle-presentations endpoint.
3+
"""
4+
from __future__ import absolute_import
5+
6+
from plotly.api.v2.utils import build_url, request
7+
8+
RESOURCE = 'spectacle-presentations'
9+
10+
11+
def create(body):
12+
"""Create a presentation."""
13+
url = build_url(RESOURCE)
14+
return request('post', url, json=body)
15+
16+
17+
def list():
18+
"""Returns the list of all users' presentations."""
19+
url = build_url(RESOURCE)
20+
return request('get', url)
21+
22+
23+
def retrieve(fid):
24+
"""Retrieve a presentation from Plotly."""
25+
url = build_url(RESOURCE, id=fid)
26+
return request('get', url)
27+
28+
29+
def update(fid, content):
30+
"""Completely update the writable."""
31+
url = build_url(RESOURCE, id=fid)
32+
return request('put', url, json=content)

plotly/figure_factory/_scatterplot.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import absolute_import
22

3-
from plotly import exceptions, optional_imports
3+
from plotly import colors, exceptions, optional_imports
44
from plotly.figure_factory import utils
55
from plotly.graph_objs import graph_objs
66
from plotly.tools import make_subplots
@@ -386,9 +386,9 @@ def scatterplot_theme(dataframe, headers, diag, size, height, width, title,
386386

387387
# Convert colormap to list of n RGB tuples
388388
if colormap_type == 'seq':
389-
foo = utils.color_parser(colormap, utils.unlabel_rgb)
389+
foo = colors.color_parser(colormap, colors.unlabel_rgb)
390390
foo = utils.n_colors(foo[0], foo[1], n_colors_len)
391-
theme = utils.color_parser(foo, utils.label_rgb)
391+
theme = colors.color_parser(foo, colors.label_rgb)
392392

393393
if colormap_type == 'cat':
394394
# leave list of colors the same way
@@ -556,9 +556,9 @@ def scatterplot_theme(dataframe, headers, diag, size, height, width, title,
556556

557557
# Convert colormap to list of n RGB tuples
558558
if colormap_type == 'seq':
559-
foo = utils.color_parser(colormap, utils.unlabel_rgb)
559+
foo = colors.color_parser(colormap, colors.unlabel_rgb)
560560
foo = utils.n_colors(foo[0], foo[1], len(intervals))
561-
theme = utils.color_parser(foo, utils.label_rgb)
561+
theme = colors.color_parser(foo, colors.label_rgb)
562562

563563
if colormap_type == 'cat':
564564
# leave list of colors the same way

plotly/package_data/default-schema.json

+9-1
Original file line numberDiff line numberDiff line change
@@ -35081,6 +35081,7 @@
3508135081
"role": "info",
3508235082
"valType": "string"
3508335083
},
35084+
"description": "",
3508435085
"editType": "calc",
3508535086
"family": {
3508635087
"arrayOk": true,
@@ -35101,6 +35102,7 @@
3510135102
"size": {
3510235103
"arrayOk": true,
3510335104
"editType": "calc",
35105+
"min": 1,
3510435106
"role": "style",
3510535107
"valType": "number"
3510635108
},
@@ -35134,6 +35136,7 @@
3513435136
"line": {
3513535137
"color": {
3513635138
"arrayOk": true,
35139+
"dflt": "grey",
3513735140
"editType": "calc",
3513835141
"role": "style",
3513935142
"valType": "color"
@@ -35148,6 +35151,7 @@
3514835151
"role": "object",
3514935152
"width": {
3515035153
"arrayOk": true,
35154+
"dflt": 1,
3515135155
"editType": "calc",
3515235156
"role": "style",
3515335157
"valType": "number"
@@ -35216,7 +35220,7 @@
3521635220
},
3521735221
"columnwidth": {
3521835222
"arrayOk": true,
35219-
"description": "The width of cells.",
35223+
"description": "The width of columns expressed as a ratio. Columns fill the available width in proportion of their specified column widths.",
3522035224
"dflt": null,
3522135225
"editType": "calc",
3522235226
"role": "style",
@@ -35345,6 +35349,7 @@
3534535349
"role": "info",
3534635350
"valType": "string"
3534735351
},
35352+
"description": "",
3534835353
"editType": "calc",
3534935354
"family": {
3535035355
"arrayOk": true,
@@ -35365,6 +35370,7 @@
3536535370
"size": {
3536635371
"arrayOk": true,
3536735372
"editType": "calc",
35373+
"min": 1,
3536835374
"role": "style",
3536935375
"valType": "number"
3537035376
},
@@ -35398,6 +35404,7 @@
3539835404
"line": {
3539935405
"color": {
3540035406
"arrayOk": true,
35407+
"dflt": "grey",
3540135408
"editType": "calc",
3540235409
"role": "style",
3540335410
"valType": "color"
@@ -35412,6 +35419,7 @@
3541235419
"role": "object",
3541335420
"width": {
3541435421
"arrayOk": true,
35422+
"dflt": 1,
3541535423
"editType": "calc",
3541635424
"role": "style",
3541735425
"valType": "number"

plotly/plotly/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
get_config,
2525
get_grid,
2626
dashboard_ops,
27+
presentation_ops,
2728
create_animations,
2829
icreate_animations
2930
)

plotly/plotly/plotly.py

+81-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
'sharing': files.FILE_CONTENT[files.CONFIG_FILE]['sharing']
4848
}
4949

50+
SHARING_ERROR_MSG = (
51+
"Whoops, sharing can only be set to either 'public', 'private', or "
52+
"'secret'."
53+
)
54+
5055
# test file permissions and make sure nothing is corrupted
5156
tools.ensure_local_plotly_files()
5257

@@ -1520,6 +1525,81 @@ def get_dashboard_names(cls):
15201525
return [str(dboard['filename']) for dboard in dashboards]
15211526

15221527

1528+
class presentation_ops:
1529+
"""
1530+
Interface to Plotly's Spectacle-Presentations API.
1531+
"""
1532+
@classmethod
1533+
def upload(cls, presentation, filename, sharing='public', auto_open=True):
1534+
"""
1535+
Function for uploading presentations to Plotly.
1536+
1537+
:param (dict) presentation: the JSON presentation to be uploaded. Use
1538+
plotly.presentation_objs.Presentation to create presentations
1539+
from a Markdown-like string.
1540+
:param (str) filename: the name of the presentation to be saved in
1541+
your Plotly account. Will overwrite a presentation of the same
1542+
name if it already exists in your files.
1543+
:param (str) sharing: can be set to either 'public', 'private'
1544+
or 'secret'. If 'public', your presentation will be viewable by
1545+
all other users. If 'private' only you can see your presentation.
1546+
If it is set to 'secret', the url will be returned with a string
1547+
of random characters appended to the url which is called a
1548+
sharekey. The point of a sharekey is that it makes the url very
1549+
hard to guess, but anyone with the url can view the presentation.
1550+
:param (bool) auto_open: automatically opens the presentation in the
1551+
browser.
1552+
1553+
See the documentation online for examples.
1554+
"""
1555+
if sharing == 'public':
1556+
world_readable = True
1557+
elif sharing in ['private', 'secret']:
1558+
world_readable = False
1559+
else:
1560+
raise exceptions.PlotlyError(
1561+
SHARING_ERROR_MSG
1562+
)
1563+
data = {
1564+
'content': json.dumps(presentation),
1565+
'filename': filename,
1566+
'world_readable': world_readable
1567+
}
1568+
1569+
# lookup if pre-existing filename already exists
1570+
try:
1571+
lookup_res = v2.files.lookup(filename)
1572+
lookup_res.raise_for_status()
1573+
matching_file = json.loads(lookup_res.content)
1574+
1575+
if matching_file['filetype'] != 'spectacle_presentation':
1576+
raise exceptions.PlotlyError(
1577+
"'{filename}' is already a {filetype} in your account. "
1578+
"You can't overwrite a file that is not a spectacle_"
1579+
"presentation. Please pick another filename.".format(
1580+
filename=filename,
1581+
filetype=matching_file['filetype']
1582+
)
1583+
)
1584+
else:
1585+
old_fid = matching_file['fid']
1586+
res = v2.spectacle_presentations.update(old_fid, data)
1587+
1588+
except exceptions.PlotlyRequestError:
1589+
res = v2.spectacle_presentations.create(data)
1590+
res.raise_for_status()
1591+
1592+
url = res.json()['web_url']
1593+
1594+
if sharing == 'secret':
1595+
url = add_share_key_to_url(url)
1596+
1597+
if auto_open:
1598+
webbrowser.open_new(res.json()['web_url'])
1599+
1600+
return url
1601+
1602+
15231603
def create_animations(figure, filename=None, sharing='public', auto_open=True):
15241604
"""
15251605
BETA function that creates plots with animations via `frames`.
@@ -1712,8 +1792,7 @@ def create_animations(figure, filename=None, sharing='public', auto_open=True):
17121792
body['share_key_enabled'] = True
17131793
else:
17141794
raise exceptions.PlotlyError(
1715-
"Whoops, sharing can only be set to either 'public', 'private', "
1716-
"or 'secret'."
1795+
SHARING_ERROR_MSG
17171796
)
17181797

17191798
response = v2.plots.create(body)

plotly/presentation_objs/__init__.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""
2+
presentation_objs
3+
4+
A wrapper for the spectacle-presentations endpoint.
5+
===========
6+
7+
"""
8+
from . presentation_objs import Presentation

0 commit comments

Comments
 (0)