Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fdd328a

Browse files
committed
Merge branch 'master' into grid_docs
2 parents ce4274a + 5586407 commit fdd328a

File tree

29 files changed

+393
-113
lines changed

29 files changed

+393
-113
lines changed

README.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ License: MIT
107107
.. _Plotly: https://plot.ly
108108
.. _Quickstart: https://plot.ly/python
109109
.. _GitHub repo: https://github.com/plotly/python-api
110-
.. _Plotly and mpld3: http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s6_matplotlylib/s6_matplotlylib.ipynb
111-
.. _Plotly and Python: http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s0_getting-started/s0_getting-started.ipynb
112-
.. _set of notebooks: http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s00_homepage/s00_homepage.ipynb
110+
.. _Plotly and mpld3: https://plot.ly/python/matplotlib-to-plotly-tutorial/
111+
.. _Plotly and Python: https://plot.ly/python/overview/
112+
.. _set of notebooks: https://plot.ly/python/user-guide/
113113
.. _plotly profile: https://plot.ly/~mpld3/
114114
.. _@plotlygraphs: https://twitter.com/plotlygraphs
115115

circle.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
machine:
2+
environment:
3+
PLOTLY_PACKAGE_ROOT: /home/ubuntu/python-api
4+
PLOTLY_CONFIG_DIR: ${HOME}/.plotly
5+
PLOTLY_PYTHON_VERSIONS: 2.6.8 2.7.8 3.3.3 3.4.1
6+
PLOTLY_CORE_REQUIREMENTS_FILE: ${PLOTLY_PACKAGE_ROOT}/requirements.txt
7+
PLOTLY_OPTIONAL_REQUIREMENTS_FILE: ${PLOTLY_PACKAGE_ROOT}/optional-requirements.txt
8+
PLOTLY_OPTIONAL_REQUIREMENTS_FILE_2_6: ${PLOTLY_PACKAGE_ROOT}/optional-requirements-2-6.txt
9+
dependencies:
10+
pre:
11+
# run all the pre-written installers (this will take a *while*)
12+
- bash circle/setup.sh
13+
# install testing tools for circle's version of things
14+
- PYENV_VERSION=2.7 && pip install nose coverage
15+
override:
16+
- PYENV_VERSION=2.7 && pip install -I .
17+
- PYENV_VERSION=2.7 && cd ~ && python -c "import plotly"
18+
test:
19+
override:
20+
21+
# run test suite in all our python versions
22+
- bash circle/test.sh
23+
24+
# # test that it imports when you don't have file permissions
25+
# - sudo chmod 400 ${PLOTLY_CONFIG_DIR} && python -c "import plotly"
26+
#
27+
# # test that setting permissions will work for import (and tests)
28+
# - sudo chmod 600 ${PLOTLY_CONFIG_DIR} && python -c "import plotly"
29+
30+
# test core things in the general 2.7 version that circle has
31+
- PYENV_VERSION=2.7 && nosetests -xv plotly/tests --with-coverage --cover-package=plotly
32+
- mkdir "${CIRCLE_ARTIFACTS}/2.7" || true
33+
- coverage html -d "${CIRCLE_ARTIFACTS}/2.7" --title=2.7

circle/setup.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/bash
2+
3+
echo "running setup routine with python versions:"
4+
for version in ${PLOTLY_PYTHON_VERSIONS[@]}; do
5+
echo " ${version}"
6+
done
7+
8+
PROGNAME=$(basename $0)
9+
function error_exit
10+
{
11+
echo -e "${PROGNAME}: ${1:-"Unknown Error"}\n" 1>&2
12+
exit 1
13+
}
14+
15+
# for each version we want, setup a functional virtual environment
16+
for version in ${PLOTLY_PYTHON_VERSIONS[@]}; do
17+
echo Setting up Python ${version}
18+
19+
# exporting this variable (in this scope) chooses the python version
20+
export PYENV_VERSION=${version}
21+
echo "Using pyenv version $(pyenv version)"
22+
23+
# install core requirements all versions need
24+
pip install -r ${PLOTLY_CORE_REQUIREMENTS_FILE} ||
25+
error_exit "${LINENO}: can't install core reqs for Python ${version}"
26+
27+
# handle funkiness around python 2.6
28+
if [ ${version:0:3} == '2.6' ]
29+
then
30+
pip install simplejson ordereddict ||
31+
error_exit "${LINENO}: can't install extras for Python ${version}"
32+
pip install -r ${PLOTLY_OPTIONAL_REQUIREMENTS_FILE_2_6} ||
33+
error_exit "${LINENO}: can't install optional for Python ${version}"
34+
else
35+
pip install -r ${PLOTLY_OPTIONAL_REQUIREMENTS_FILE} ||
36+
error_exit "${LINENO}: can't install optional for Python ${version}"
37+
fi
38+
39+
# install some test tools
40+
pip install nose coverage ||
41+
error_exit "${LINENO}: can't install test tools for Python ${version}"
42+
done

circle/test.sh

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/bin/bash
2+
3+
echo "running test routine with python versions:"
4+
for version in ${PLOTLY_PYTHON_VERSIONS[@]}; do
5+
echo " ${version}"
6+
done
7+
8+
PROGNAME=$(basename $0)
9+
function error_exit
10+
{
11+
echo -e "${PROGNAME}: ${1:-"Unknown Error"}\n" 1>&2
12+
exit 1
13+
}
14+
15+
# for each version we want, setup a functional virtual environment
16+
for version in ${PLOTLY_PYTHON_VERSIONS[@]}; do
17+
echo Testing Python ${version}
18+
19+
# exporting this variable (in this scope) chooses the python version
20+
export PYENV_VERSION=${version}
21+
echo "Using pyenv version $(pyenv version)"
22+
23+
echo "install plotly (ignoring possibly cached versions)"
24+
pip install -I ${PLOTLY_PACKAGE_ROOT} ||
25+
error_exit "${LINENO}: can't install plotly package from project root"
26+
27+
echo "import plotly to create .plotly dir if DNE"
28+
python -c 'import plotly' ||
29+
error_exit "${LINENO}: can't import plotly package"
30+
31+
# echo "${HOME}"
32+
# echo "${PLOTLY_CONFIG_DIR}"
33+
#
34+
# # test that it imports when you don't have write permissions
35+
# sudo chmod -R 444 ${PLOTLY_CONFIG_DIR} && python -c "import plotly" ||
36+
# error_exit "${LINENO}: permissions test 444 on .plotly dir failed"
37+
#
38+
# # test that setting write permissions will work for import (and tests)
39+
# sudo chmod -R 666 ${PLOTLY_CONFIG_DIR} && python -c "import plotly" ||
40+
# error_exit "${LINENO}: permissions test 666 on .plotly dir failed"
41+
42+
echo "running tests for Python ${version} as user '$(whoami)'"
43+
nosetests -xv plotly/tests --with-coverage --cover-package=plotly ||
44+
error_exit "${LINENO}: test suite failed for Python ${version}"
45+
mkdir "${CIRCLE_ARTIFACTS}/${PYENV_VERSION}" || true
46+
coverage html -d "${CIRCLE_ARTIFACTS}/${PYENV_VERSION}" \
47+
--title=${PYENV_VERSION}
48+
49+
done

optional-requirements-2-6.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
### Optional Dependencies for Additional Plotly Functionality ###
2+
### ###
3+
### To install, run: ###
4+
### $ pip install -r optional-requirements.txt ###
5+
### ###
6+
###################################################################
7+
8+
## numpy (technically, this is covered by matplotlib's deps) ##
9+
numpy
10+
11+
## matplotlylib dependencies ##
12+
matplotlib==1.3.1
13+
14+
## testing dependencies ##
15+
nose==1.3.3
16+
17+
## pandas deps for some matplotlib functionality ##
18+
pandas

optional-requirements.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@
55
### ###
66
###################################################################
77

8+
## numpy (technically, this is covered by matplotlib's deps) ##
9+
numpy
10+
811
## matplotlylib dependencies ##
912
matplotlib==1.3.1
1013

1114
## testing dependencies ##
1215
nose==1.3.3
1316

1417
## ipython dependencies ##
15-
ipython[all]
18+
ipython[all]
19+
20+
## pandas deps for some matplotlib functionality ##
21+
pandas

plotly/exceptions.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
1717
"""
1818
import json
19+
import six
1920

2021
## Base Plotly Error ##
2122

@@ -36,7 +37,9 @@ def __init__(self, requests_exception):
3637
if 'json' in content_type:
3738
content = requests_exception.response.content
3839
if content != '':
39-
res_payload = json.loads(requests_exception.response.content)
40+
res_payload = json.loads(
41+
requests_exception.response.content.decode('utf8')
42+
)
4043
if 'detail' in res_payload:
4144
self.message = res_payload['detail']
4245
else:
@@ -66,7 +69,7 @@ def __str__(self):
6669
NON_UNIQUE_COLUMN_MESSAGE = (
6770
"Yikes, plotly grids currently "
6871
"can't have duplicate column names. Rename "
69-
"the column \"{}\" and try again."
72+
"the column \"{0}\" and try again."
7073
)
7174
## Would Cause Server Errors ##
7275

plotly/graph_objs/graph_objs.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def to_string(self, level=0, indent=4, eol='\n',
215215
216216
Example:
217217
218-
print obj.to_string()
218+
print(obj.to_string())
219219
220220
Keyword arguments:
221221
level (default = 0) -- set number of indentations to start with
@@ -323,14 +323,14 @@ def __setitem__(self, key, value):
323323
return super(PlotlyDict, self).__setitem__(key, value)
324324

325325
def _assign_id_to_src(self, src_name, src_value):
326-
if isinstance(src_value, basestring):
326+
if isinstance(src_value, six.string_types):
327327
src_id = src_value
328328
else:
329329
try:
330330
src_id = src_value.id
331331
except:
332-
err = ("{} does not have an `id` property. "
333-
"{} needs to be assigned to either an "
332+
err = ("{0} does not have an `id` property. "
333+
"{1} needs to be assigned to either an "
334334
"object with an `id` (like a "
335335
"plotly.grid_objs.Column) or a string. "
336336
"The `id` is a unique identifier "
@@ -430,7 +430,7 @@ def strip_style(self):
430430
elif not hasattr(self[key], '__iter__'):
431431
del self[key]
432432
except KeyError: # TODO: Update the JSON
433-
# print "'type' not in {0} for {1}".format(obj_key, key)
433+
# print("'type' not in {0} for {1}".format(obj_key, key))
434434
pass
435435

436436
def get_data(self):
@@ -605,7 +605,7 @@ def to_string(self, level=0, indent=4, eol='\n',
605605
606606
Example:
607607
608-
print obj.to_string()
608+
print(obj.to_string())
609609
610610
Keyword arguments:
611611
level (default = 0) -- set number of indentations to start with
@@ -759,7 +759,7 @@ def to_string(self, level=0, indent=4, eol='\n',
759759
760760
Example:
761761
762-
print obj.to_string()
762+
print(obj.to_string())
763763
764764
Keyword arguments:
765765
level (default = 0) -- set number of indentations to start with
@@ -962,7 +962,7 @@ def to_string(self, level=0, indent=4, eol='\n',
962962
963963
Example:
964964
965-
print obj.to_string()
965+
print(obj.to_string())
966966
967967
Keyword arguments:
968968
level (default = 0) -- set number of indentations to start with

plotly/grid_objs/grid_objs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ def __str__(self):
7676
return string.format(name=self.name, data=data_string, id=self.id)
7777

7878
def __repr__(self):
79-
return 'Column("{}", {})'.format(self.data, self.name)
79+
return 'Column("{0}", {1})'.format(self.data, self.name)
8080

81-
def to_json(self):
81+
def to_plotly_json(self):
8282
return {'name': self.name, 'data': self.data}
8383

8484

plotly/matplotlylib/mpltools.py

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ def prep_ticks(ax, index, ax_type, props):
386386
for i in range(1, len(dticks) - 1)]):
387387
dtick = tickvalues[1] - tickvalues[0]
388388
else:
389-
warnings.warn("'linear' {}-axis tick spacing not even, "
389+
warnings.warn("'linear' {0}-axis tick spacing not even, "
390390
"ignoring mpl tick formatting.".format(ax_type))
391391
raise TypeError
392392
except (IndexError, TypeError):
@@ -413,7 +413,7 @@ def prep_ticks(ax, index, ax_type, props):
413413
math.log10(props['ylim'][1])]
414414
else:
415415
axis_dict = dict(range=None, type='linear')
416-
warnings.warn("Converted non-base10 {}-axis log scale to 'linear'"
416+
warnings.warn("Converted non-base10 {0}-axis log scale to 'linear'"
417417
"".format(ax_type))
418418
else:
419419
return dict()
@@ -422,13 +422,17 @@ def prep_ticks(ax, index, ax_type, props):
422422
if ax_type == 'x' and 'DateFormatter' in formatter:
423423
axis_dict['type'] = 'date'
424424
try:
425-
axis_dict['tick0'] = mpl_dates_to_datestrings(axis_dict['tick0'])
425+
axis_dict['tick0'] = mpl_dates_to_datestrings(
426+
axis_dict['tick0'], formatter
427+
)
426428
except KeyError:
427429
pass
428430
finally:
429431
axis_dict.pop('dtick', None)
430432
axis_dict.pop('autotick', None)
431-
axis_dict['range'] = mpl_dates_to_datestrings(props['xlim'])
433+
axis_dict['range'] = mpl_dates_to_datestrings(
434+
props['xlim'], formatter
435+
)
432436

433437
if formatter == 'LogFormatterMathtext':
434438
axis_dict['exponentformat'] = 'e'
@@ -457,22 +461,39 @@ def prep_xy_axis(ax, props, x_bounds, y_bounds):
457461
return xaxis, yaxis
458462

459463

460-
def mpl_dates_to_datestrings(mpl_dates, format_string="%Y-%m-%d %H:%M:%S"):
461-
"""Convert matplotlib dates to formatted datestrings for plotly.
464+
def mpl_dates_to_datestrings(dates, mpl_formatter):
465+
"""Convert matplotlib dates to iso-formatted-like time strings.
466+
467+
Plotly's accepted format: "YYYY-MM-DD HH:MM:SS" (e.g., 2001-01-01 00:00:00)
462468
463469
Info on mpl dates: http://matplotlib.org/api/dates_api.html
464470
465471
"""
466-
try:
467-
date_times = matplotlib.dates.num2date(mpl_dates, tz=pytz.utc)
468-
time_strings = [date_time.strftime(format_string)
469-
for date_time in date_times]
470-
if len(time_strings) > 1:
471-
return time_strings
472-
else:
473-
return time_strings[0]
474-
except TypeError:
475-
return mpl_dates
472+
_dates = dates
473+
474+
# this is a pandas datetime formatter, times show up in floating point days
475+
# since the epoch (1970-01-01T00:00:00+00:00)
476+
if mpl_formatter == "TimeSeries_DateFormatter":
477+
try:
478+
dates = matplotlib.dates.epoch2num(
479+
[date*24*60*60 for date in dates]
480+
)
481+
dates = matplotlib.dates.num2date(dates, tz=pytz.utc)
482+
except:
483+
return _dates
484+
485+
# the rest of mpl dates are in floating point days since
486+
# (0001-01-01T00:00:00+00:00) + 1. I.e., (0001-01-01T00:00:00+00:00) == 1.0
487+
# according to mpl --> try num2date(1)
488+
else:
489+
try:
490+
dates = matplotlib.dates.num2date(dates, tz=pytz.utc)
491+
except:
492+
return _dates
493+
494+
time_stings = [' '.join(date.isoformat().split('+')[0].split('T'))
495+
for date in dates]
496+
return time_stings
476497

477498

478499
DASH_MAP = {

plotly/matplotlylib/renderer.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,9 @@ def draw_bar(self, coll):
258258
[bar['x1'] for bar in trace])
259259
if self.x_is_mpl_date:
260260
x = [bar['x0'] for bar in trace]
261-
x = mpltools.mpl_dates_to_datestrings(x)
261+
formatter = (self.current_mpl_ax.get_xaxis()
262+
.get_major_formatter().__class__.__name__)
263+
x = mpltools.mpl_dates_to_datestrings(x, formatter)
262264
else:
263265
self.msg += " Attempting to draw a horizontal bar chart\n"
264266
old_rights = [bar_props['x1'] for bar_props in trace]
@@ -367,8 +369,10 @@ def draw_marked_line(self, **props):
367369
line=line,
368370
marker=marker)
369371
if self.x_is_mpl_date:
372+
formatter = (self.current_mpl_ax.get_xaxis()
373+
.get_major_formatter().__class__.__name__)
370374
marked_line['x'] = mpltools.mpl_dates_to_datestrings(
371-
marked_line['x']
375+
marked_line['x'], formatter
372376
)
373377
self.plotly_fig['data'] += marked_line,
374378
self.msg += " Heck yeah, I drew that line\n"

0 commit comments

Comments
 (0)