diff --git a/circle.yml b/circle.yml index 24515d3de41..540e863960b 100644 --- a/circle.yml +++ b/circle.yml @@ -2,10 +2,9 @@ machine: environment: PLOTLY_PACKAGE_ROOT: /home/ubuntu/python-api PLOTLY_CONFIG_DIR: ${HOME}/.plotly - PLOTLY_PYTHON_VERSIONS: 2.6.8 2.7.8 3.3.3 3.4.1 + PLOTLY_PYTHON_VERSIONS: 2.7.8 3.3.3 3.4.1 PLOTLY_CORE_REQUIREMENTS_FILE: ${PLOTLY_PACKAGE_ROOT}/requirements.txt PLOTLY_OPTIONAL_REQUIREMENTS_FILE: ${PLOTLY_PACKAGE_ROOT}/optional-requirements.txt - PLOTLY_OPTIONAL_REQUIREMENTS_FILE_2_6: ${PLOTLY_PACKAGE_ROOT}/optional-requirements-2-6.txt dependencies: override: diff --git a/circle/setup.sh b/circle/setup.sh index 7d6f06a6852..a0ddc2afb39 100644 --- a/circle/setup.sh +++ b/circle/setup.sh @@ -33,17 +33,8 @@ for version in ${PLOTLY_PYTHON_VERSIONS[@]}; do pip install -r ${PLOTLY_CORE_REQUIREMENTS_FILE} || error_exit "${LINENO}: can't install core reqs for Python ${version}" - # handle funkiness around python 2.6 - if [ ${version:0:3} == '2.6' ] - then - pip install -e '.[PY2.6]' || - error_exit "${LINENO}: can't install extras for Python ${version}" - pip install -r ${PLOTLY_OPTIONAL_REQUIREMENTS_FILE_2_6} || - error_exit "${LINENO}: can't install optional for Python ${version}" - else - pip install -r ${PLOTLY_OPTIONAL_REQUIREMENTS_FILE} || - error_exit "${LINENO}: can't install optional for Python ${version}" - fi + pip install -r ${PLOTLY_OPTIONAL_REQUIREMENTS_FILE} || + error_exit "${LINENO}: can't install optional for Python ${version}" # install some test tools pip install nose coverage || diff --git a/optional-requirements-2-6.txt b/optional-requirements-2-6.txt deleted file mode 100644 index c37ceaeb364..00000000000 --- a/optional-requirements-2-6.txt +++ /dev/null @@ -1,18 +0,0 @@ -### Optional Dependencies for Additional Plotly Functionality ### -### ### -### To install, run: ### -### $ pip install -r optional-requirements.txt ### -### ### -################################################################### - -## numpy (technically, this is covered by matplotlib's deps) ## -numpy - -## matplotlylib dependencies ## -matplotlib==1.3.1 - -## testing dependencies ## -nose==1.3.3 - -## pandas deps for some matplotlib functionality ## -pandas diff --git a/plotly/__init__.py b/plotly/__init__.py index 49961b33da8..36b8131c039 100644 --- a/plotly/__init__.py +++ b/plotly/__init__.py @@ -28,5 +28,5 @@ from __future__ import absolute_import -from plotly import plotly, graph_objs, grid_objs, tools, utils, session +from plotly import plotly, graph_objs, grid_objs, tools, utils, session, offline from plotly.version import __version__ diff --git a/plotly/offline/__init__.py b/plotly/offline/__init__.py new file mode 100644 index 00000000000..df04b62cc01 --- /dev/null +++ b/plotly/offline/__init__.py @@ -0,0 +1,10 @@ +""" +offline +====== +This module provides offline functionality. +""" +from . offline import ( + download_plotlyjs, + init_notebook_mode, + iplot +) diff --git a/plotly/offline/offline.py b/plotly/offline/offline.py new file mode 100644 index 00000000000..cd137d56f0a --- /dev/null +++ b/plotly/offline/offline.py @@ -0,0 +1,189 @@ +""" Plotly Offline + A module to use Plotly's graphing library with Python + without connecting to a public or private plotly enterprise + server. +""" +from __future__ import absolute_import + +import uuid +import json +import os +import requests + +from plotly import utils +from plotly import tools +from plotly.exceptions import PlotlyError +from plotly import session + +PLOTLY_OFFLINE_DIRECTORY = plotlyjs_path = os.path.expanduser( + os.path.join(*'~/.plotly/plotlyjs'.split('/'))) +PLOTLY_OFFLINE_BUNDLE = os.path.join(PLOTLY_OFFLINE_DIRECTORY, + 'plotly-ipython-offline-bundle.js') + + +__PLOTLY_OFFLINE_INITIALIZED = False + + +def download_plotlyjs(download_url): + if not os.path.exists(PLOTLY_OFFLINE_DIRECTORY): + os.makedirs(PLOTLY_OFFLINE_DIRECTORY) + + res = requests.get(download_url) + res.raise_for_status() + + with open(PLOTLY_OFFLINE_BUNDLE, 'wb') as f: + f.write(res.content) + + print('\n'.join([ + 'Success! Now start an IPython notebook and run the following ' + + 'code to make your first offline graph:', + '', + 'import plotly', + 'plotly.offline.init_notebook_mode() ' + '# run at the start of every ipython notebook', + 'plotly.offline.iplot([{"x": [1, 2, 3], "y": [3, 1, 6]}])' + ])) + + +def init_notebook_mode(): + """ + Initialize Plotly Offline mode in an IPython Notebook. + Run this function at the start of an IPython notebook + to load the necessary javascript files for creating + Plotly graphs with plotly.offline.iplot. + """ + if not tools._ipython_imported: + raise ImportError('`iplot` can only run inside an IPython Notebook.') + from IPython.display import HTML, display + + if not os.path.exists(PLOTLY_OFFLINE_BUNDLE): + raise PlotlyError('Plotly Offline source file at {source_path} ' + 'is not found.\n' + 'If you have a Plotly Offline license, then try ' + 'running plotly.offline.download_plotlyjs(url) ' + 'with a licensed download url.\n' + "Don't have a Plotly Offline license? " + 'Contact sales@plot.ly learn more about licensing.\n' + 'Questions? support@plot.ly.' + .format(source_path=PLOTLY_OFFLINE_BUNDLE)) + + global __PLOTLY_OFFLINE_INITIALIZED + __PLOTLY_OFFLINE_INITIALIZED = True + display(HTML('')) + + +def iplot(figure_or_data, show_link=True, link_text='Export to plot.ly'): + """ + Draw plotly graphs inside an IPython notebook without + connecting to an external server. + To save the chart to Plotly Cloud or Plotly Enterprise, use + `plotly.plotly.iplot`. + To embed an image of the chart, use `plotly.image.ishow`. + + figure_or_data -- a plotly.graph_objs.Figure or plotly.graph_objs.Data or + dict or list that describes a Plotly graph. + See https://plot.ly/python/ for examples of + graph descriptions. + + Keyword arguments: + show_link (default=True) -- display a link in the bottom-right corner of + of the chart that will export the chart to + Plotly Cloud or Plotly Enterprise + link_text (default='Export to plot.ly') -- the text of export link + + Example: + ``` + from plotly.offline import init_notebook_mode, iplot + init_notebook_mode() + + iplot([{'x': [1, 2, 3], 'y': [5, 2, 7]}]) + ``` + """ + if not __PLOTLY_OFFLINE_INITIALIZED: + raise PlotlyError('\n'.join([ + 'Plotly Offline mode has not been initialized in this notebook. ' + 'Run: ', + '', + 'import plotly', + 'plotly.offline.init_notebook_mode() ' + '# run at the start of every ipython notebook', + ])) + if not tools._ipython_imported: + raise ImportError('`iplot` can only run inside an IPython Notebook.') + + from IPython.display import HTML, display + if isinstance(figure_or_data, dict): + data = figure_or_data['data'] + layout = figure_or_data.get('layout', {}) + else: + data = figure_or_data + layout = {} + + width = layout.get('width', '100%') + height = layout.get('height', 525) + try: + float(width) + except (ValueError, TypeError): + pass + else: + width = str(width) + 'px' + + try: + float(width) + except (ValueError, TypeError): + pass + else: + width = str(width) + 'px' + + plotdivid = uuid.uuid4() + jdata = json.dumps(data, cls=utils.PlotlyJSONEncoder) + jlayout = json.dumps(layout, cls=utils.PlotlyJSONEncoder) + + if show_link is False: + link_text = '' + + plotly_platform_url = session.get_session_config().get('plotly_domain', + 'https://plot.ly') + if (plotly_platform_url != 'https://plot.ly' and + link_text == 'Export to plot.ly'): + + link_domain = plotly_platform_url\ + .replace('https://', '')\ + .replace('http://', '') + link_text = link_text.replace('plot.ly', link_domain) + + display(HTML( + '' + )) + + script = '\n'.join([ + 'Plotly.plot("{id}", {data}, {layout}).then(function() {{', + ' $(".{id}.loading").remove();', + '}})' + ]).format(id=plotdivid, + data=jdata, + layout=jlayout, + link_text=link_text) + + display(HTML('' + '