diff --git a/.circleci/config.yml b/.circleci/config.yml
index 5e58717cc4..b02e989c31 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -339,7 +339,7 @@ jobs:
command: |
cd packages/python/plotly
locale
- tox -e py37-core -- -a '!nodev'
+ tox -e py37-core -- -k 'not nodev'
no_output_timeout: 20m
- run:
name: Commit
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0f801f6554..f00ad21c4d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,16 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
+## [4.5.3] - 2020-03-05
+
+### Updated
+
+- Removed development dependency on `nose` testing framework [#2217](https://github.com/plotly/plotly.py/pull/2217)
+
+### Fixed
+
+ - JupyterLab extension now compatible with JupyterLab 2.0 [#2245](https://github.com/plotly/plotly.py/pull/2245) with thanks to [@consideRatio](https://github.com/consideRatio) for the contribution!
+
## [4.5.2] - 2020-02-24
### Fixed
@@ -11,6 +21,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [4.5.1] - 2020-02-19
### Updated
+
- Updated Plotly.js to version 1.52.2. See the [plotly.js CHANGELOG](https://github.com/plotly/plotly.js/releases/tag/v1.52.2) for more information on bug fixes.
### Fixed
diff --git a/README.md b/README.md
index 36831a7732..0d230a119e 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@
## Quickstart
-`pip install plotly==4.5.2`
+`pip install plotly==4.5.3`
Inside [Jupyter notebook](https://jupyter.org/install) (installable with `pip install "notebook>=5.3" "ipywidgets>=7.2"`):
@@ -75,13 +75,13 @@ Built on top of [plotly.js](https://github.com/plotly/plotly.js), `plotly.py` is
plotly.py may be installed using pip...
```
-pip install plotly==4.5.2
+pip install plotly==4.5.3
```
or conda.
```
-conda install -c plotly plotly=4.5.2
+conda install -c plotly plotly=4.5.3
```
### Jupyter Notebook Support
@@ -128,10 +128,10 @@ set NODE_OPTIONS=--max-old-space-size=4096
jupyter labextension install @jupyter-widgets/jupyterlab-manager@1.1 --no-build
# FigureWidget support
-jupyter labextension install plotlywidget@1.5.2 --no-build
+jupyter labextension install plotlywidget@1.5.3 --no-build
# and jupyterlab renderer support
-jupyter labextension install jupyterlab-plotly@1.5.2 --no-build
+jupyter labextension install jupyterlab-plotly@1.5.3 --no-build
# Build extensions (must be done to activate extensions since --no-build is used above)
jupyter lab build
diff --git a/contributing.md b/contributing.md
index 84cc1841d1..78d1727f58 100644
--- a/contributing.md
+++ b/contributing.md
@@ -1,6 +1,6 @@
# Contributing
-The bottom line. Follow your Nose, or our Nose. Write-run-love tests :fist:.
+Thank you for contributing to plotly.py!
## Code of Conduct
@@ -128,34 +128,40 @@ classes based on the new schema.
We take advantage of two tools to run tests:
* [`tox`](https://tox.readthedocs.io/en/latest/), which is both a virtualenv management and test tool.
-* [`nose`](https://nose.readthedocs.org/en/latest/), which is is an extension of Python's unittest
+* [`pytest`](https://docs.pytest.org/en/latest/), a powerful framework for unit testing.
-### Running Tests with `nose`
+### Running Tests with `pytest`
Since our tests cover *all* the functionality, to prevent tons of errors from showing up and having to parse through a messy output, you'll need to install `optional-requirements.txt` as explained above.
-After you've done that, go ahead and follow (y)our Nose!
+After you've done that, go ahead and run the test suite!
```bash
-nosetests -w packages/python/plotly/plotly/tests/
+pytest packages/python/plotly/plotly/tests/
```
Or for more *verbose* output:
```bash
-nosetests -w packages/python/plotly/plotly/tests/ -v
+pytest -v packages/python/plotly/plotly/tests/
```
Either of those will run *every* test we've written for the Python API. You can get more granular by running something like:
```bash
-nosetests -w packages/python/plotly/plotly/tests/test_core/
+pytest packages/python/plotly/plotly/tests/test_core/
```
... or even more granular by running something like:
```bash
-nosetests plotly/tests/test_plotly/test_plot.py
+pytest plotly/tests/test_plotly/test_plot.py
+```
+
+or for a specfic test function
+
+```bash
+pytest plotly/tests/test_plotly/test_plot.py::test_function
```
### Running tests with `tox`
@@ -187,16 +193,16 @@ Where `TOXENV` is the environment list you want to use when invoking `tox` from
* `tox` will automatically manage a virtual env for each environment you want to test in.
* You only have to run `tox` and know that the module is working in both `Python 2` and `Python 3`.
-Finally, `tox` allows you to pass in additional command line arguments that are formatted in (by us) in the `tox.ini` file, see `{posargs}`. This is setup to help with our `nose attr` configuration. To run only tests that are *not* tagged with `slow`, you could use the following command:
+Finally, `tox` allows you to pass in additional command line arguments that are formatted in (by us) in the `tox.ini` file, see `{posargs}`. This is setup to help with our configuration of [pytest markers](http://doc.pytest.org/en/latest/example/markers.html), which are set up in `packages/python/plotly/pytest.ini`. To run only tests that are *not* tagged with `nodev`, you could use the following command:
```bash
-tox -- -a '!slow'
+tox -- -a '!nodev'
```
-Note that anything after `--` is substituted in for `{posargs}` in the tox.ini. For completeness, because it's reasonably confusing, if you want to force a match for *multiple* `nose attr` tags, you comma-separate the tags like so:
+Note that anything after `--` is substituted in for `{posargs}` in the tox.ini. For completeness, because it's reasonably confusing, if you want to force a match for *multiple* `pytest` marker tags, you comma-separate the tags like so:
```bash
-tox -- -a '!slow','!matplotlib'
+tox -- -a '!nodev','!matplotlib'
```
### Writing Tests
diff --git a/doc/python/axes.md b/doc/python/axes.md
index eea8f8daed..cdab606651 100644
--- a/doc/python/axes.md
+++ b/doc/python/axes.md
@@ -741,6 +741,27 @@ fig.update_yaxes(domain=(0.25, 0.75))
fig.show()
```
+#### Synchronizing axes in subplots with `matches`
+
+Using `facet_col` from `plotly.express` let [zoom](https://help.plot.ly/zoom-pan-hover-controls/#step-3-zoom-in-and-zoom-out-autoscale-the-plot) and [pan](https://help.plot.ly/zoom-pan-hover-controls/#step-6-pan-along-axes) each facet to the same range implicitly. However, if the subplots are created with `make_subplots`, the axis needs to be updated with `matches` parameter to update all the subplots accordingly.
+
+Zoom in one trace below, to see the other subplots zoomed to the same x-axis range. To pan all the subplots, click and drag from the center of x-axis to the side:
+
+```python
+import plotly.graph_objects as go
+from plotly.subplots import make_subplots
+import numpy as np
+
+N = 20
+x = np.linspace(0, 1, N)
+
+fig = make_subplots(1, 3)
+for i in range(1, 4):
+ fig.add_trace(go.Scatter(x=x, y=np.random.random(N)), 1, i)
+fig.update_xaxes(matches='x')
+fig.show()
+```
+
#### Reference
See https://plot.ly/python/reference/#layout-xaxis and https://plot.ly/python/reference/#layout-yaxis for more information and chart attribute options!
diff --git a/doc/python/facet-plots.md b/doc/python/facet-plots.md
index 999a23fd0e..6df50ae549 100644
--- a/doc/python/facet-plots.md
+++ b/doc/python/facet-plots.md
@@ -118,3 +118,24 @@ fig.show()
```python
```
+
+### Synchronizing axes in subplots with `matches`
+
+Using `facet_col` from `plotly.express` let [zoom](https://help.plot.ly/zoom-pan-hover-controls/#step-3-zoom-in-and-zoom-out-autoscale-the-plot) and [pan](https://help.plot.ly/zoom-pan-hover-controls/#step-6-pan-along-axes) each facet to the same range implicitly. However, if the subplots are created with `make_subplots`, the axis needs to be updated with `matches` parameter to update all the subplots accordingly.
+
+Zoom in one trace below, to see the other subplots zoomed to the same x-axis range. To pan all the subplots, click and drag from the center of x-axis to the side:
+
+```python
+import plotly.graph_objects as go
+from plotly.subplots import make_subplots
+import numpy as np
+
+N = 20
+x = np.linspace(0, 1, N)
+
+fig = make_subplots(1, 3)
+for i in range(1, 4):
+ fig.add_trace(go.Scatter(x=x, y=np.random.random(N)), 1, i)
+fig.update_xaxes(matches='x')
+fig.show()
+```
diff --git a/doc/python/figurewidget-app.md b/doc/python/figurewidget-app.md
index aeeb61013a..99a17c3116 100644
--- a/doc/python/figurewidget-app.md
+++ b/doc/python/figurewidget-app.md
@@ -31,6 +31,7 @@ jupyter:
page_type: example_index
permalink: python/figurewidget-app/
thumbnail: thumbnail/multi-widget.jpg
+ redirect_from: /python/slider-widget/
---
#### NYC Flights Database
diff --git a/doc/python/figurewidget.md b/doc/python/figurewidget.md
index 63de6a9c8a..3fe143b1d5 100644
--- a/doc/python/figurewidget.md
+++ b/doc/python/figurewidget.md
@@ -31,6 +31,7 @@ jupyter:
page_type: example_index
permalink: python/figurewidget/
thumbnail: thumbnail/figurewidget-overview.gif
+ redirect_from: /python/ipython-widgets/
---
#### Create a Simple FigureWidget
diff --git a/doc/python/getting-started.md b/doc/python/getting-started.md
index 8428cffe03..157f91a45c 100644
--- a/doc/python/getting-started.md
+++ b/doc/python/getting-started.md
@@ -49,13 +49,13 @@ Thanks to deep integration with the [orca](https://github.com/plotly/orca) image
plotly.py may be installed using pip...
```
-$ pip install plotly==4.5.2
+$ pip install plotly==4.5.3
```
or conda.
```
-$ conda install -c plotly plotly=4.5.2
+$ conda install -c plotly plotly=4.5.3
```
This package contains everything you need to write figures to standalone HTML files.
@@ -144,10 +144,10 @@ set NODE_OPTIONS=--max-old-space-size=4096
jupyter labextension install @jupyter-widgets/jupyterlab-manager@1.1 --no-build
# jupyterlab renderer support
-jupyter labextension install jupyterlab-plotly@1.5.2 --no-build
+jupyter labextension install jupyterlab-plotly@1.5.3 --no-build
# FigureWidget support
-jupyter labextension install plotlywidget@1.5.2 --no-build
+jupyter labextension install plotlywidget@1.5.3 --no-build
# Build extensions (must be done to activate extensions since --no-build is used above)
jupyter lab build
diff --git a/doc/python/interactive-html-export.md b/doc/python/interactive-html-export.md
new file mode 100644
index 0000000000..5c919946c9
--- /dev/null
+++ b/doc/python/interactive-html-export.md
@@ -0,0 +1,65 @@
+---
+jupyter:
+ jupytext:
+ notebook_metadata_filter: all
+ text_representation:
+ extension: .md
+ format_name: markdown
+ format_version: '1.2'
+ jupytext_version: 1.3.1
+ kernelspec:
+ display_name: Python 3
+ language: python
+ name: python3
+ language_info:
+ codemirror_mode:
+ name: ipython
+ version: 3
+ file_extension: .py
+ mimetype: text/x-python
+ name: python
+ nbconvert_exporter: python
+ pygments_lexer: ipython3
+ version: 3.6.8
+ plotly:
+ description: Plotly allows you to save interactive HTML versions of your figures
+ to your local disk.
+ display_as: file_settings
+ language: python
+ layout: base
+ name: Interactive HTML Export
+ order: 30
+ page_type: u-guide
+ permalink: python/interactive-html-export/
+ thumbnail: thumbnail/static-image-export.png
+---
+
+### Interactive vs Static Export
+
+Plotly figures are interactive when viewed in a web browser: you can hover over data points, pan and zoom axes, and show and hide traces by clicking or double-clicking on the legend. You can export figures either to [static image file formats like PNG, JEPG, SVG or PDF](/python/static-image-export/) or you can export them to HTML files which can be opened in a browser. This page explains how to do the latter.
+
+
+### Saving to an HTML file
+
+Any figure can be saved an HTML file using the `write_html` method. These HTML files can be opened in any web browser to access the fully interactive figure.
+
+```python
+import plotly.express as px
+
+fig =px.scatter(x=range(10), y=range(10))
+fig.write_html("path/to/file.html")
+```
+
+
+### Controlling the size of the HTML file
+
+By default, the resulting HTML file is a fully self-contained HTML file which can be uploaded to a web server or shared via email or other file-sharing mechanisms. The downside to this approach is that the file is very large (5Mb+) because it contains an inlined copy of the Plotly.js library required to make the figure interactive. This can be controlled via the `include_plotlyjs` argument (see below).
+
+
+### Full Parameter Documentation
+
+```python
+import plotly.graph_objects as go
+
+help(go.Figure.write_html)
+```
diff --git a/doc/python/legend.md b/doc/python/legend.md
index 9a2996ff17..d11c58305a 100644
--- a/doc/python/legend.md
+++ b/doc/python/legend.md
@@ -243,7 +243,30 @@ fig.update_layout(
fig.show()
```
-### Size of Legend Items
+#### Hide the Trace Implicitly
+
+`Graph_objects` traces have a `visible` attribute. If set to `legendonly`, the trace is hidden from the graph implicitly. Click on the name in the legend to display the hidden trace.
+
+```python
+import plotly.graph_objects as go
+
+fig = go.Figure()
+
+fig.add_trace(go.Scatter(
+ x=[1, 2, 3, 4, 5],
+ y=[1, 2, 3, 4, 5],
+))
+
+fig.add_trace(go.Scatter(
+ x=[1, 2, 3, 4, 5],
+ y=[5, 4, 3, 2, 1],
+ visible='legendonly'
+))
+
+fig.show()
+```
+
+#### Size of Legend Items
In this example [itemsizing](https://plot.ly/python/reference/#layout-legend-itemsizing) attribute determines the legend items symbols remain constant, regardless of how tiny/huge the bubbles would be in the graph.
diff --git a/doc/python/marker-style.md b/doc/python/marker-style.md
index 865ff1052f..3b54cc0064 100644
--- a/doc/python/marker-style.md
+++ b/doc/python/marker-style.md
@@ -313,113 +313,29 @@ The basic symbols are: `circle`, `square`, `diamond`, `cross`, `x`, `triangle`,
Each basic symbol is also represented by a number. Adding 100 to that number is equivalent to appending the suffix "-open" to a symbol name. Adding 200 is equivalent to appending "-dot" to a symbol name. Adding 300 is equivalent to appending "-open-dot" or "dot-open" to a symbol name.
-In the following figures, hover over a symbol to see its name or number. Set the `marker_symbol` attribute equal to that name or number to change the marker symbol in your figure.
-
-#### Basic Symbols
-
-```python
-import plotly.graph_objects as go
-
-fig = go.Figure()
-
-fig.update_layout(title="Basic Symbols")
-
-fig.update_xaxes(showticklabels=False)
-fig.update_yaxes(showticklabels=False)
-
-for index in range(27):
- fig.add_trace(go.Scatter(x=[(index % 6)], y=[index // 6], name="",
- marker_symbol=index, marker_color='black',
- marker_size=10, showlegend=False, mode="markers+text",
- textposition="middle right", text=f'{index}',
- hovertemplate=f'Symbol Number: {index}'))
-
-fig.show()
-```
-
-#### All Symbols
+In the following figure, hover over a symbol to see its name or number. Set the `marker_symbol` attribute equal to that name or number to change the marker symbol in your figure.
```python
import plotly.graph_objects as go
-
-symbols = [0, 'circle', 100, 'circle-open', 200, 'circle-dot', 300,
- 'circle-open-dot', 1, 'square', 101, 'square-open', 201,
- 'square-dot', 301, 'square-open-dot', 2, 'diamond', 102,
- 'diamond-open', 202, 'diamond-dot', 302,
- 'diamond-open-dot', 3, 'cross', 103, 'cross-open', 203,
- 'cross-dot', 303, 'cross-open-dot', 4, 'x', 104, 'x-open',
- 204, 'x-dot', 304, 'x-open-dot', 5, 'triangle-up', 105,
- 'triangle-up-open', 205, 'triangle-up-dot', 305,
- 'triangle-up-open-dot', 6, 'triangle-down', 106,
- 'triangle-down-open', 206, 'triangle-down-dot', 306,
- 'triangle-down-open-dot', 7, 'triangle-left', 107,
- 'triangle-left-open', 207, 'triangle-left-dot', 307,
- 'triangle-left-open-dot', 8, 'triangle-right', 108,
- 'triangle-right-open', 208, 'triangle-right-dot', 308,
- 'triangle-right-open-dot', 9, 'triangle-ne', 109,
- 'triangle-ne-open', 209, 'triangle-ne-dot', 309,
- 'triangle-ne-open-dot', 10, 'triangle-se', 110,
- 'triangle-se-open', 210, 'triangle-se-dot', 310,
- 'triangle-se-open-dot', 11, 'triangle-sw', 111,
- 'triangle-sw-open', 211, 'triangle-sw-dot', 311,
- 'triangle-sw-open-dot', 12, 'triangle-nw', 112,
- 'triangle-nw-open', 212, 'triangle-nw-dot', 312,
- 'triangle-nw-open-dot', 13, 'pentagon', 113,
- 'pentagon-open', 213, 'pentagon-dot', 313,
- 'pentagon-open-dot', 14, 'hexagon', 114, 'hexagon-open',
- 214, 'hexagon-dot', 314, 'hexagon-open-dot', 15,
- 'hexagon2', 115, 'hexagon2-open', 215, 'hexagon2-dot',
- 315, 'hexagon2-open-dot', 16, 'octagon', 116,
- 'octagon-open', 216, 'octagon-dot', 316,
- 'octagon-open-dot', 17, 'star', 117, 'star-open', 217,
- 'star-dot', 317, 'star-open-dot', 18, 'hexagram', 118,
- 'hexagram-open', 218, 'hexagram-dot', 318,
- 'hexagram-open-dot', 19, 'star-triangle-up', 119,
- 'star-triangle-up-open', 219, 'star-triangle-up-dot', 319,
- 'star-triangle-up-open-dot', 20, 'star-triangle-down',
- 120, 'star-triangle-down-open', 220,
- 'star-triangle-down-dot', 320,
- 'star-triangle-down-open-dot', 21, 'star-square', 121,
- 'star-square-open', 221, 'star-square-dot', 321,
- 'star-square-open-dot', 22, 'star-diamond', 122,
- 'star-diamond-open', 222, 'star-diamond-dot', 322,
- 'star-diamond-open-dot', 23, 'diamond-tall', 123,
- 'diamond-tall-open', 223, 'diamond-tall-dot', 323,
- 'diamond-tall-open-dot', 24, 'diamond-wide', 124,
- 'diamond-wide-open', 224, 'diamond-wide-dot', 324,
- 'diamond-wide-open-dot', 25, 'hourglass', 125,
- 'hourglass-open', 26, 'bowtie', 126, 'bowtie-open', 27,
- 'circle-cross', 127, 'circle-cross-open', 28, 'circle-x',
- 128, 'circle-x-open', 29, 'square-cross', 129,
- 'square-cross-open', 30, 'square-x', 130, 'square-x-open',
- 31, 'diamond-cross', 131, 'diamond-cross-open', 32,
- 'diamond-x', 132, 'diamond-x-open', 33, 'cross-thin', 133,
- 'cross-thin-open', 34, 'x-thin', 134, 'x-thin-open', 35,
- 'asterisk', 135, 'asterisk-open', 36, 'hash', 136,
- 'hash-open', 236, 'hash-dot', 336, 'hash-open-dot', 37,
- 'y-up', 137, 'y-up-open', 38, 'y-down', 138,
- 'y-down-open', 39, 'y-left', 139, 'y-left-open', 40,
- 'y-right', 140, 'y-right-open', 41, 'line-ew', 141,
- 'line-ew-open', 42, 'line-ns', 142, 'line-ns-open', 43,
- 'line-ne', 143, 'line-ne-open', 44, 'line-nw', 144,
- 'line-nw-open']
-
-fig = go.Figure()
-
-fig.update_layout(title="Custom Marker Symbols", height=800)
-
-fig.update_xaxes(showticklabels=False)
-fig.update_yaxes(showticklabels=False)
-
-for index, symbol in enumerate(symbols[::2]):
- fig.add_trace(go.Scatter(x=[(index % 16)], y=[(index // 16)],
- marker_symbol=symbol, marker_color=index,
- marker_size=20, showlegend=False, mode="markers+text",
- name='',
- hovertemplate=f'Symbol Name: {symbols[2*index + 1]}
Symbol Number: {symbols[2*index]}',
- textfont_size=8
- ))
-
+from plotly.validators.scatter.marker import SymbolValidator
+
+raw_symbols = SymbolValidator().values
+namestems = []
+namevariants = []
+symbols = []
+for i in range(0,len(raw_symbols),2):
+ name = raw_symbols[i+1]
+ symbols.append(raw_symbols[i])
+ namestems.append(name.replace("-open", "").replace("-dot", ""))
+ namevariants.append(name[len(namestems[-1]):])
+
+fig = go.Figure(go.Scatter(mode="markers", x=namevariants, y=namestems, marker_symbol=symbols,
+ marker_line_color="midnightblue", marker_color="lightskyblue",
+ marker_line_width=2, marker_size=15,
+ hovertemplate="name: %{y}%{x}
number: %{marker.symbol}"))
+fig.update_layout(title="Mouse over symbols for name & number!",
+ xaxis_range=[-1,4], yaxis_range=[len(set(namestems)),-1],
+ margin=dict(b=0,r=0), xaxis_side="top", height=1200, width=400)
fig.show()
```
diff --git a/doc/python/static-image-export.md b/doc/python/static-image-export.md
index 16dd6c0abe..387fbdd24d 100644
--- a/doc/python/static-image-export.md
+++ b/doc/python/static-image-export.md
@@ -35,10 +35,12 @@ jupyter:
thumbnail: thumbnail/static-image-export.png
---
-
-### Static Image Export
-It's possible to programmatically export figures as high quality static images while fully offline.
+### Interactive vs Static Export
+
+Plotly figures are interactive when viewed in a web browser: you can hover over data points, pan and zoom axes, and show and hide traces by clicking or double-clicking on the legend. You can export figures either to static image file formats like PNG, JEPG, SVG or PDF or you can [export them to HTML files which can be opened in a browser and remain interactive](/python/interactive-html-export/). This page explains how to do the former.
+
+
#### Install Dependencies
Static image generation requires the [orca](https://github.com/plotly/orca) commandline utility and the [psutil](https://github.com/giampaolo/psutil) and [requests](https://2.python-requests.org/en/master/) Python libraries. There are 3 general approach to installing these dependencies.
diff --git a/doc/python/subplots.md b/doc/python/subplots.md
index d1f411797d..50cf161d45 100644
--- a/doc/python/subplots.md
+++ b/doc/python/subplots.md
@@ -296,6 +296,28 @@ fig.update_layout(height=600, width=600,
fig.show()
```
+### Subplots with Shared Colorscale
+
+To share colorscale information in multiple subplots, you can use [coloraxis](https://plot.ly/javascript/reference/#scatter-marker-line-coloraxis).
+
+```python
+from plotly.subplots import make_subplots
+import plotly.graph_objects as go
+
+fig = make_subplots(rows=1, cols=2, shared_yaxes=True)
+
+fig.add_trace(go.Bar(x=[1, 2, 3], y=[4, 5, 6],
+ marker=dict(color=[4, 5, 6], coloraxis="coloraxis")),
+ 1, 1)
+
+fig.add_trace(go.Bar(x=[1, 2, 3], y=[2, 3, 5],
+ marker=dict(color=[2, 3, 5], coloraxis="coloraxis")),
+ 1, 2)
+
+fig.update_layout(coloraxis=dict(colorscale='Bluered_r'), showlegend=False)
+fig.show()
+```
+
#### Custom Sized Subplot with Subplot Titles
The `specs` argument to `make_subplots` is used to configure per-subplot options. `specs` must be a 2-dimension list with dimensions that match those provided as the `rows` and `cols` arguments. The elements of `specs` may either be `None`, indicating no subplot should be initialized starting with this grid cell, or a dictionary containing subplot options. The `colspan` subplot option specifies the number of grid columns that the subplot starting in the given cell should occupy. If unspecified, `colspan` defaults to 1.
diff --git a/packages/javascript/jupyterlab-plotly/package-lock.json b/packages/javascript/jupyterlab-plotly/package-lock.json
index da0d9da013..8a2339f6f6 100644
--- a/packages/javascript/jupyterlab-plotly/package-lock.json
+++ b/packages/javascript/jupyterlab-plotly/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "jupyterlab-plotly",
- "version": "1.5.2",
+ "version": "1.5.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -30,12 +30,120 @@
}
},
"@jupyterlab/rendermime-interfaces": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@jupyterlab/rendermime-interfaces/-/rendermime-interfaces-1.3.0.tgz",
- "integrity": "sha512-04ohT/xdTcdp/TKuNMqY1MLwh7IWyjbMrQXiuwanE8xo52fIe6OIK0DENwc6VDMej1+8NVSU7rX42urLCex0sA==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@jupyterlab/rendermime-interfaces/-/rendermime-interfaces-2.0.0.tgz",
+ "integrity": "sha512-1BRpxIppycFmJtV5kq+BVcQT80k3PflMmDsSITXFUspX20SiEktjZcSfzUplTwkp6pSXlr2QCLTV2rQE00dGNA==",
+ "requires": {
+ "@lumino/coreutils": "1.4.2",
+ "@lumino/widgets": "1.11.1"
+ }
+ },
+ "@lumino/algorithm": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@lumino/algorithm/-/algorithm-1.2.3.tgz",
+ "integrity": "sha512-XBJ/homcm7o8Y9G6MzYvf0FF7SVqUCzvkIO01G2mZhCOnkZZhZ9c4uNOcE2VjSHNxHv2WU0l7d8rdhyKhmet+A=="
+ },
+ "@lumino/collections": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@lumino/collections/-/collections-1.2.3.tgz",
+ "integrity": "sha512-lrSTb7kru/w8xww8qWqHHhHO3GkoQeXST2oNkOEbWNEO4wuBIHoKPSOmXpUwu58UykBUfd5hL5wbkeTzyNMONg==",
+ "requires": {
+ "@lumino/algorithm": "1.2.3"
+ }
+ },
+ "@lumino/commands": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/@lumino/commands/-/commands-1.10.1.tgz",
+ "integrity": "sha512-HGtXtqKD1WZJszJ42u2DyM3sgxrLal66IoHSJjbn2ygcEVCKDK73NSzoaQtXFtiissMedzKl8aIRXB3uyeEOlw==",
+ "requires": {
+ "@lumino/algorithm": "1.2.3",
+ "@lumino/coreutils": "1.4.2",
+ "@lumino/disposable": "1.3.5",
+ "@lumino/domutils": "1.1.7",
+ "@lumino/keyboard": "1.1.6",
+ "@lumino/signaling": "1.3.5",
+ "@lumino/virtualdom": "1.6.1"
+ }
+ },
+ "@lumino/coreutils": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/@lumino/coreutils/-/coreutils-1.4.2.tgz",
+ "integrity": "sha512-SmQ4YDANe25rZd0bLoW7LVAHmgySjkrJmyNPnPW0GrpBt2u4/6D+EQJ8PCCMNWuJvrljBCdlmgOFsT38qYhfcw=="
+ },
+ "@lumino/disposable": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-1.3.5.tgz",
+ "integrity": "sha512-IWDAd+nysBnwLhEtW7M62PVk84OEex9OEktZsS6V+19n/o8/Rw4ccL0pt0GFby01CsVK0YcELDoDaMUZsMiAmA==",
+ "requires": {
+ "@lumino/algorithm": "1.2.3",
+ "@lumino/signaling": "1.3.5"
+ }
+ },
+ "@lumino/domutils": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@lumino/domutils/-/domutils-1.1.7.tgz",
+ "integrity": "sha512-NPysY8XfpCvLNvDe+z1caIUPxOLXWRPQMUAjOj/EhggRyXadan6Lm/5uO6M9S5gW/v9QUXT4+1Sxe3WXz0nRCA=="
+ },
+ "@lumino/dragdrop": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-1.5.1.tgz",
+ "integrity": "sha512-MFg/hy6hHdPwBZypBue5mlrBzjoNrtBQzzJW+kbM5ftAOvS99ZRgyMMlMQcbsHd+6yib9NOQ64Hd8P8uZEWTdw==",
+ "requires": {
+ "@lumino/coreutils": "1.4.2",
+ "@lumino/disposable": "1.3.5"
+ }
+ },
+ "@lumino/keyboard": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/@lumino/keyboard/-/keyboard-1.1.6.tgz",
+ "integrity": "sha512-W6pqe0TXRfGOoz1ZK1PRmuGZUWpmdoJArrzwmduUf0t2r06yl56S7w76gxrB7ExTidNPPaOWydGIosPgdgZf5A=="
+ },
+ "@lumino/messaging": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@lumino/messaging/-/messaging-1.3.3.tgz",
+ "integrity": "sha512-J+0m1aywl64I9/dr9fzE9IwC+eq90T5gUi1hCXP1MFnZh4aLUymmRV5zFw1CNh/vYlNnEu72xxEuhfCfuhiy8g==",
+ "requires": {
+ "@lumino/algorithm": "1.2.3",
+ "@lumino/collections": "1.2.3"
+ }
+ },
+ "@lumino/properties": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/@lumino/properties/-/properties-1.1.6.tgz",
+ "integrity": "sha512-QnZa1IB7sr4Tawf0OKvwgZAptxDRK7DUAMJ71zijXNXH4FlxyThzOWXef51HHFsISKYa8Rn3rysOwtc62XkmXw=="
+ },
+ "@lumino/signaling": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-1.3.5.tgz",
+ "integrity": "sha512-6jniKrLrJOXKJmaJyU7hr6PBzE4GJ5Wms5hc/yzNKKDBxGSEPdtNJlW3wTNUuSTTtF/9ItN8A8ZC/G0yIu53Tw==",
+ "requires": {
+ "@lumino/algorithm": "1.2.3"
+ }
+ },
+ "@lumino/virtualdom": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/@lumino/virtualdom/-/virtualdom-1.6.1.tgz",
+ "integrity": "sha512-+KdzSw8TCPwvK6qhZr4xTyp6HymvEb2Da0xPdi4RsVUNhYf2gBI03uidXHx76Vx5OIbEgCn1B+0srxvm2ZbWsQ==",
"requires": {
- "@phosphor/coreutils": "1.3.1",
- "@phosphor/widgets": "1.8.1"
+ "@lumino/algorithm": "1.2.3"
+ }
+ },
+ "@lumino/widgets": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@lumino/widgets/-/widgets-1.11.1.tgz",
+ "integrity": "sha512-f4QDe6lVNPcjL8Vb20BiP0gzbT1rx0/1Hc719u5oW9c0Z/xrXMWwNhnb/zYM/kBBVBe3omLmCfJOiNuE0oZl0A==",
+ "requires": {
+ "@lumino/algorithm": "1.2.3",
+ "@lumino/commands": "1.10.1",
+ "@lumino/coreutils": "1.4.2",
+ "@lumino/disposable": "1.3.5",
+ "@lumino/domutils": "1.1.7",
+ "@lumino/dragdrop": "1.5.1",
+ "@lumino/keyboard": "1.1.6",
+ "@lumino/messaging": "1.3.3",
+ "@lumino/properties": "1.1.6",
+ "@lumino/signaling": "1.3.5",
+ "@lumino/virtualdom": "1.6.1"
}
},
"@mapbox/geojson-area": {
@@ -100,113 +208,6 @@
"resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz",
"integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q=="
},
- "@phosphor/algorithm": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@phosphor/algorithm/-/algorithm-1.1.3.tgz",
- "integrity": "sha512-+dkdYTBglR+qGnLVQdCvYojNZMGxf+xSl1Jeksha3pm7niQktSFz2aR5gEPu/nI5LM8T8slTpqE4Pjvq8P+IVA=="
- },
- "@phosphor/collections": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@phosphor/collections/-/collections-1.1.3.tgz",
- "integrity": "sha512-J2U1xd2e5LtqoOJt4kynrjDNeHhVpJjuY2/zA0InS5kyOuWmvy79pt/KJ22n0LBNcU/fjkImqtQmbrC2Z4q2xQ==",
- "requires": {
- "@phosphor/algorithm": "1.1.3"
- }
- },
- "@phosphor/commands": {
- "version": "1.6.3",
- "resolved": "https://registry.npmjs.org/@phosphor/commands/-/commands-1.6.3.tgz",
- "integrity": "sha512-PYNHWv6tbXAfAtKiqXuT0OBJvwbJ+RRTV60MBykMF7Vqz9UaZ9n2e/eB2EAGEFccF0PnjTCvBEZgarwwMVi8Hg==",
- "requires": {
- "@phosphor/algorithm": "1.1.3",
- "@phosphor/coreutils": "1.3.1",
- "@phosphor/disposable": "1.2.0",
- "@phosphor/domutils": "1.1.3",
- "@phosphor/keyboard": "1.1.3",
- "@phosphor/signaling": "1.2.3"
- }
- },
- "@phosphor/coreutils": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/@phosphor/coreutils/-/coreutils-1.3.1.tgz",
- "integrity": "sha512-9OHCn8LYRcPU/sbHm5v7viCA16Uev3gbdkwqoQqlV+EiauDHl70jmeL7XVDXdigl66Dz0LI11C99XOxp+s3zOA=="
- },
- "@phosphor/disposable": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@phosphor/disposable/-/disposable-1.2.0.tgz",
- "integrity": "sha512-4PoWoffdrLyWOW5Qv7I8//owvZmv57YhaxetAMWeJl13ThXc901RprL0Gxhtue2ZxL2PtUjM1207HndKo2FVjA==",
- "requires": {
- "@phosphor/algorithm": "1.1.3",
- "@phosphor/signaling": "1.2.3"
- }
- },
- "@phosphor/domutils": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@phosphor/domutils/-/domutils-1.1.3.tgz",
- "integrity": "sha512-5CtLAhURQXXHhNXfQydDk/luG1cDVnhlu/qw7gz8/9pht0KXIAmNg/M0LKxx2oJ9+YMNCLVWxAnHAU0yrDpWSA=="
- },
- "@phosphor/dragdrop": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/@phosphor/dragdrop/-/dragdrop-1.3.3.tgz",
- "integrity": "sha512-+SrlGsVQwY8OHCWxE/Zvihpk6Rc6bytJDqOUUTZqdL8hvM9QZeopAFioPDxuo1pTj87Um6cR4ekvbTU4KZ/90w==",
- "requires": {
- "@phosphor/coreutils": "1.3.1",
- "@phosphor/disposable": "1.2.0"
- }
- },
- "@phosphor/keyboard": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@phosphor/keyboard/-/keyboard-1.1.3.tgz",
- "integrity": "sha512-dzxC/PyHiD6mXaESRy6PZTd9JeK+diwG1pyngkyUf127IXOEzubTIbu52VSdpGBklszu33ws05BAGDa4oBE4mQ=="
- },
- "@phosphor/messaging": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@phosphor/messaging/-/messaging-1.2.3.tgz",
- "integrity": "sha512-89Ps4uSRNOEQoepB/0SDoyPpNUWd6VZnmbMetmeXZJHsuJ1GLxtnq3WBdl7UCVNsw3W9NC610pWaDCy/BafRlg==",
- "requires": {
- "@phosphor/algorithm": "1.1.3",
- "@phosphor/collections": "1.1.3"
- }
- },
- "@phosphor/properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@phosphor/properties/-/properties-1.1.3.tgz",
- "integrity": "sha512-GiglqzU77s6+tFVt6zPq9uuyu/PLQPFcqZt914ZhJ4cN/7yNI/SLyMzpYZ56IRMXvzK9TUgbRna6URE3XAwFUg=="
- },
- "@phosphor/signaling": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@phosphor/signaling/-/signaling-1.2.3.tgz",
- "integrity": "sha512-DMwS0m9OgfY5ljpTsklRQPUQpTyg4obz85FyImRDacUVxUVbas95djIDEbU4s1TMzdHBBO+gfki3V4giXUvXzw==",
- "requires": {
- "@phosphor/algorithm": "1.1.3"
- }
- },
- "@phosphor/virtualdom": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@phosphor/virtualdom/-/virtualdom-1.1.3.tgz",
- "integrity": "sha512-V8PHhhnZCRa5esrC4q5VthqlLtxTo9ZV1mZ6b4YEloapca1S1nggZSQhrSlltXQjtYNUaWJZUZ/BlFD8wFtIEQ==",
- "requires": {
- "@phosphor/algorithm": "1.1.3"
- }
- },
- "@phosphor/widgets": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/@phosphor/widgets/-/widgets-1.8.1.tgz",
- "integrity": "sha512-OY5T0nAioYTitPks/lCHm7a6QpjRB/XviIT2j6WtYm5J1U8MluIPpClqZ/NQbZfm23BYpmJeiQQyZA+5YphsDA==",
- "requires": {
- "@phosphor/algorithm": "1.1.3",
- "@phosphor/commands": "1.6.3",
- "@phosphor/coreutils": "1.3.1",
- "@phosphor/disposable": "1.2.0",
- "@phosphor/domutils": "1.1.3",
- "@phosphor/dragdrop": "1.3.3",
- "@phosphor/keyboard": "1.1.3",
- "@phosphor/messaging": "1.2.3",
- "@phosphor/properties": "1.1.3",
- "@phosphor/signaling": "1.2.3",
- "@phosphor/virtualdom": "1.1.3"
- }
- },
"@plotly/d3-sankey": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/@plotly/d3-sankey/-/d3-sankey-0.7.2.tgz",
@@ -4228,9 +4229,9 @@
}
},
"typescript": {
- "version": "3.1.6",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz",
- "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==",
+ "version": "3.7.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz",
+ "integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==",
"dev": true
},
"uglify-js": {
diff --git a/packages/javascript/jupyterlab-plotly/package.json b/packages/javascript/jupyterlab-plotly/package.json
index f57b5ba5d9..3fa2beecdc 100644
--- a/packages/javascript/jupyterlab-plotly/package.json
+++ b/packages/javascript/jupyterlab-plotly/package.json
@@ -1,6 +1,6 @@
{
"name": "jupyterlab-plotly",
- "version": "1.5.2",
+ "version": "1.5.3",
"description": "The plotly JupyterLab extension",
"author": "The plotly.py team",
"license": "MIT",
@@ -28,14 +28,14 @@
"devDependencies": {
"rimraf": "^2.6.1",
"ify-loader": "^1.1.0",
- "typescript": "~3.1.1"
+ "typescript": "~3.7.0"
},
"dependencies": {
"plotly.js": "^1.52.1",
"@types/plotly.js": "1.44.28",
- "@jupyterlab/rendermime-interfaces": "^1.3.0",
- "@phosphor/messaging": "^1.2.3",
- "@phosphor/widgets": "^1.8.1",
+ "@jupyterlab/rendermime-interfaces": "^1.3.0 || ^2.0.0",
+ "@lumino/messaging": "^1.2.3",
+ "@lumino/widgets": "^1.8.1",
"lodash": "^4.17.4"
},
"jupyterlab": {
diff --git a/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts b/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts
index 90197b158c..b724e5df55 100644
--- a/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts
+++ b/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts
@@ -1,9 +1,9 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
-import { Widget } from '@phosphor/widgets';
+import { Widget } from '@lumino/widgets';
-import { Message } from '@phosphor/messaging';
+import { Message } from '@lumino/messaging';
import { IRenderMime } from '@jupyterlab/rendermime-interfaces';
diff --git a/packages/javascript/plotlywidget/package-lock.json b/packages/javascript/plotlywidget/package-lock.json
index 40a8aa604c..6273fc79f8 100644
--- a/packages/javascript/plotlywidget/package-lock.json
+++ b/packages/javascript/plotlywidget/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "plotlywidget",
- "version": "1.5.2",
+ "version": "1.5.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/packages/javascript/plotlywidget/package.json b/packages/javascript/plotlywidget/package.json
index 4eb14c5132..7bd03cf5c7 100644
--- a/packages/javascript/plotlywidget/package.json
+++ b/packages/javascript/plotlywidget/package.json
@@ -1,6 +1,6 @@
{
"name": "plotlywidget",
- "version": "1.5.2",
+ "version": "1.5.3",
"description": "The plotly JupyterLab extension",
"author": "The plotly.py team",
"license": "MIT",
diff --git a/packages/python/chart-studio/chart_studio/tests/test_core/test_tools/test_get_embed.py b/packages/python/chart-studio/chart_studio/tests/test_core/test_tools/test_get_embed.py
index bbb6499fca..77709176e5 100644
--- a/packages/python/chart-studio/chart_studio/tests/test_core/test_tools/test_get_embed.py
+++ b/packages/python/chart-studio/chart_studio/tests/test_core/test_tools/test_get_embed.py
@@ -2,7 +2,7 @@
from unittest import TestCase
-from nose.tools import raises
+import pytest
import chart_studio.tools as tls
from _plotly_utils.exceptions import PlotlyError
@@ -13,10 +13,10 @@ def test_get_valid_embed():
tls.get_embed(url)
-@raises(PlotlyError)
def test_get_invalid_embed():
url = "https://plot.ly/~PlotBot/a/"
- tls.get_embed(url)
+ with pytest.raises(PlotlyError):
+ tls.get_embed(url)
class TestGetEmbed(TestCase):
diff --git a/packages/python/chart-studio/chart_studio/tests/test_optional/test_matplotlylib/test_plot_mpl.py b/packages/python/chart-studio/chart_studio/tests/test_optional/test_matplotlylib/test_plot_mpl.py
index ac35292846..a4b2bf52a5 100644
--- a/packages/python/chart-studio/chart_studio/tests/test_optional/test_matplotlylib/test_plot_mpl.py
+++ b/packages/python/chart-studio/chart_studio/tests/test_optional/test_matplotlylib/test_plot_mpl.py
@@ -7,13 +7,12 @@
"""
from __future__ import absolute_import
-from nose.plugins.attrib import attr
-from nose.tools import raises
import _plotly_utils.exceptions
from plotly import optional_imports
from chart_studio.plotly import plotly as py
from unittest import TestCase
+import pytest
matplotlylib = optional_imports.get_module("plotly.matplotlylib")
@@ -21,26 +20,25 @@
import matplotlib.pyplot as plt
-@attr("matplotlib")
+@pytest.mark.matplotlib
class PlotMPLTest(TestCase):
def setUp(self):
py.sign_in("PlotlyImageTest", "786r5mecv0", plotly_domain="https://plot.ly")
- @raises(_plotly_utils.exceptions.PlotlyGraphObjectError)
def test_update_type_error(self):
fig, ax = plt.subplots()
ax.plot([1, 2, 3])
update = []
- py.plot_mpl(fig, update=update, filename="nosetests", auto_open=False)
+ with pytest.raises(_plotly_utils.exceptions.PlotlyGraphObjectError):
+ py.plot_mpl(fig, update=update, filename="nosetests", auto_open=False)
- @raises(KeyError)
def test_update_validation_error(self):
fig, ax = plt.subplots()
ax.plot([1, 2, 3])
update = {"invalid": "anything"}
- py.plot_mpl(fig, update=update, filename="nosetests", auto_open=False)
+ with pytest.raises(KeyError):
+ py.plot_mpl(fig, update=update, filename="nosetests", auto_open=False)
- @attr("slow")
def test_update(self):
fig, ax = plt.subplots()
ax.plot([1, 2, 3])
diff --git a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_file/test_file.py b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_file/test_file.py
index 3b3746414a..4dccef1446 100644
--- a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_file/test_file.py
+++ b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_file/test_file.py
@@ -8,14 +8,12 @@
import random
import string
-from nose.plugins.attrib import attr
from chart_studio import plotly as py
from chart_studio.exceptions import PlotlyRequestError
from chart_studio.tests.utils import PlotlyTestCase
-@attr("slow")
class FolderAPITestCase(PlotlyTestCase):
def setUp(self):
super(FolderAPITestCase, self).setUp()
diff --git a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_figure/test_get_figure.py b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_figure/test_get_figure.py
index 69b6da830c..b0c4ca68ba 100644
--- a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_figure/test_get_figure.py
+++ b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_figure/test_get_figure.py
@@ -10,7 +10,6 @@
from unittest import skipIf
import six
-from nose.plugins.attrib import attr
import _plotly_utils.exceptions
from chart_studio import exceptions
@@ -38,7 +37,6 @@ def is_trivial(obj):
class GetFigureTest(PlotlyTestCase):
- @attr("slow")
def test_get_figure(self):
un = "PlotlyImageTest"
ak = "786r5mecv0"
@@ -46,7 +44,6 @@ def test_get_figure(self):
py.sign_in(un, ak)
py.get_figure("PlotlyImageTest", str(file_id))
- @attr("slow")
def test_get_figure_with_url(self):
un = "PlotlyImageTest"
ak = "786r5mecv0"
@@ -62,7 +59,6 @@ def test_get_figure_invalid_1(self):
with self.assertRaises(exceptions.PlotlyError):
py.get_figure(url)
- @attr("slow")
def test_get_figure_invalid_2(self):
un = "PlotlyImageTest"
ak = "786r5mecv0"
@@ -80,7 +76,6 @@ def test_get_figure_invalid_3(self):
with self.assertRaises(ValueError):
py.get_figure(url)
- @attr("slow")
def test_get_figure_does_not_exist(self):
un = "PlotlyImageTest"
ak = "786r5mecv0"
@@ -89,7 +84,6 @@ def test_get_figure_does_not_exist(self):
with self.assertRaises(_plotly_utils.exceptions.PlotlyError):
py.get_figure(url)
- @attr("slow")
def test_get_figure_raw(self):
un = "PlotlyImageTest"
ak = "786r5mecv0"
diff --git a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_requests/test_get_requests.py b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_requests/test_get_requests.py
index a57487f310..1f7c96369f 100644
--- a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_requests/test_get_requests.py
+++ b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_requests/test_get_requests.py
@@ -9,7 +9,6 @@
import requests
import six
-from nose.plugins.attrib import attr
import json as _json
from chart_studio.tests.utils import PlotlyTestCase
@@ -25,7 +24,6 @@
class GetRequestsTest(PlotlyTestCase):
- @attr("slow")
def test_user_does_not_exist(self):
username = "user_does_not_exist"
api_key = "invalid-apikey"
@@ -47,7 +45,6 @@ def test_user_does_not_exist(self):
self.assertEqual(response.status_code, 404)
self.assertEqual(content["error"], error_message)
- @attr("slow")
def test_file_does_not_exist(self):
username = "PlotlyImageTest"
api_key = "786r5mecv0"
@@ -68,7 +65,6 @@ def test_file_does_not_exist(self):
self.assertEqual(response.status_code, 404)
self.assertEqual(content["error"], error_message)
- @attr("slow")
def test_wrong_api_key(self): # TODO: does this test the right thing?
username = "PlotlyImageTest"
api_key = "invalid-apikey"
@@ -85,7 +81,6 @@ def test_wrong_api_key(self): # TODO: does this test the right thing?
# Locked File
# TODO
- @attr("slow")
def test_private_permission_defined(self):
username = "PlotlyImageTest"
api_key = "786r5mecv0"
@@ -105,7 +100,6 @@ def test_private_permission_defined(self):
# Private File that is shared
# TODO
- @attr("slow")
def test_missing_headers(self):
file_owner = "get_test_user"
file_id = 0
@@ -121,7 +115,6 @@ def test_missing_headers(self):
content = _json.loads(response.content.decode("unicode_escape"))
self.assertEqual(response.status_code, 422)
- @attr("slow")
def test_valid_request(self):
username = "PlotlyImageTest"
api_key = "786r5mecv0"
diff --git a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_grid/test_grid.py b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_grid/test_grid.py
index 669dd46f55..ac542e70fb 100644
--- a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_grid/test_grid.py
+++ b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_grid/test_grid.py
@@ -11,7 +11,6 @@
import string
from unittest import skip
-from nose.plugins.attrib import attr
from chart_studio import plotly as py
from chart_studio.exceptions import InputError, PlotlyRequestError
@@ -54,11 +53,9 @@ def upload_and_return_grid(self):
return g
# Nominal usage
- @attr("slow")
def test_grid_upload(self):
self.upload_and_return_grid()
- @attr("slow")
def test_grid_upload_in_new_folder(self):
g = self.get_grid()
path = "new folder: {0}/grid in folder {1}".format(
@@ -66,7 +63,6 @@ def test_grid_upload_in_new_folder(self):
)
py.grid_ops.upload(g, path, auto_open=False)
- @attr("slow")
def test_grid_upload_in_existing_folder(self):
g = self.get_grid()
folder = random_filename()
@@ -75,19 +71,16 @@ def test_grid_upload_in_existing_folder(self):
path = "existing folder: {0}/grid in folder {1}".format(folder, filename)
py.grid_ops.upload(g, path, auto_open=False)
- @attr("slow")
def test_column_append(self):
g = self.upload_and_return_grid()
new_col = Column([1, 5, 3], "new col")
py.grid_ops.append_columns([new_col], grid=g)
- @attr("slow")
def test_row_append(self):
g = self.upload_and_return_grid()
new_rows = [[1, 2], [10, 20]]
py.grid_ops.append_rows(new_rows, grid=g)
- @attr("slow")
def test_plot_from_grid(self):
g = self.upload_and_return_grid()
url = py.plot(
@@ -97,7 +90,6 @@ def test_plot_from_grid(self):
)
return url, g
- @attr("slow")
def test_get_figure_from_references(self):
url, g = self.test_plot_from_grid()
fig = py.get_figure(url)
@@ -143,7 +135,6 @@ def test_row_append_of_non_uploaded_grid(self):
py.grid_ops.append_rows(rows, grid=g)
# Input Errors
- @attr("slow")
def test_unequal_length_rows(self):
g = self.upload_and_return_grid()
rows = [[1, 2], ["to", "many", "cells"]]
@@ -158,7 +149,6 @@ def test_duplicate_columns(self):
Grid([c1, c2])
# Test delete
- @attr("slow")
def test_delete_grid(self):
g = self.get_grid()
fn = random_filename()
diff --git a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_image/test_image.py b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_image/test_image.py
index d9c5253c82..594454d7f1 100644
--- a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_image/test_image.py
+++ b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_image/test_image.py
@@ -5,79 +5,60 @@
import os
import itertools
import warnings
-
-from nose.plugins.attrib import attr
+import pytest
import _plotly_utils.exceptions
from chart_studio.plotly import plotly as py
-from chart_studio.tests.utils import PlotlyTestCase
-
-
-@attr("slow")
-class TestImage(PlotlyTestCase):
- def setUp(self):
- super(TestImage, self).setUp()
- py.sign_in("PlotlyImageTest", "786r5mecv0")
- self.data = [{"x": [1, 2, 3], "y": [3, 1, 6]}]
-
-
-def _generate_image_get_returns_valid_image_test(image_format, width, height, scale):
- def test(self):
- # TODO: better understand why this intermittently fails. See #649
- num_attempts = 5
- for i in range(num_attempts):
- if i > 0:
- warnings.warn("image test intermittently failed, retrying...")
- try:
- image = py.image.get(self.data, image_format, width, height, scale)
- if image_format in ["png", "jpeg"]:
- assert imghdr.what("", image) == image_format
- return
- except (KeyError, _plotly_utils.exceptions.PlotlyError):
- if i == num_attempts - 1:
- raise
- return test
-
-
-def _generate_image_save_as_saves_valid_image(image_format, width, height, scale):
- def _test(self):
- f, filename = tempfile.mkstemp(".{}".format(image_format))
- py.image.save_as(
- self.data,
- filename,
- format=image_format,
- width=width,
- height=height,
- scale=scale,
- )
- if image_format in ["png", "jpeg"]:
- assert imghdr.what(filename) == image_format
- else:
- assert os.path.getsize(filename) > 0
+from chart_studio.tests.utils import PlotlyTestCase
- os.remove(filename)
- return _test
+@pytest.fixture
+def setup_image():
+ py.sign_in("PlotlyImageTest", "786r5mecv0")
+ data = [{"x": [1, 2, 3], "y": [3, 1, 6]}]
+ return data
-kwargs = {
- "format": ["png", "jpeg", "pdf", "svg", "emf"],
- "width": [None, 300],
- "height": [None, 300],
- "scale": [None, 5],
-}
-for args in itertools.product(
- kwargs["format"], kwargs["width"], kwargs["height"], kwargs["scale"]
+@pytest.mark.parametrize("image_format", ("png", "jpeg", "pdf", "svg", "emf"))
+@pytest.mark.parametrize("width", (None, 300))
+@pytest.mark.parametrize("height", (None, 300))
+@pytest.mark.parametrize("scale", (None, 3))
+def test_image_get_returns_valid_image_test(
+ setup_image, image_format, width, height, scale
):
- for test_generator in [
- _generate_image_get_returns_valid_image_test,
- _generate_image_save_as_saves_valid_image,
- ]:
-
- _test = test_generator(*args)
- arg_string = ", ".join([str(a) for a in args])
- test_name = test_generator.__name__.replace("_generate", "test")
- test_name += "({})".format(arg_string)
- setattr(TestImage, test_name, _test)
+ # TODO: better understand why this intermittently fails. See #649
+ data = setup_image
+ num_attempts = 2
+ for i in range(num_attempts):
+ if i > 0:
+ warnings.warn("image test intermittently failed, retrying...")
+ try:
+ image = py.image.get(data, image_format, width, height, scale)
+ if image_format in ["png", "jpeg"]:
+ assert imghdr.what("", image) == image_format
+ return
+ except (KeyError, _plotly_utils.exceptions.PlotlyError):
+ if i == num_attempts - 1:
+ raise
+
+
+@pytest.mark.parametrize("image_format", ("png", "jpeg", "pdf", "svg", "emf"))
+@pytest.mark.parametrize("width", (None, 300))
+@pytest.mark.parametrize("height", (None, 300))
+@pytest.mark.parametrize("scale", (None, 3))
+def test_image_save_as_saves_valid_image(
+ setup_image, image_format, width, height, scale
+):
+ data = setup_image
+ f, filename = tempfile.mkstemp(".{}".format(image_format))
+ py.image.save_as(
+ data, filename, format=image_format, width=width, height=height, scale=scale,
+ )
+ if image_format in ["png", "jpeg"]:
+ assert imghdr.what(filename) == image_format
+ else:
+ assert os.path.getsize(filename) > 0
+
+ os.remove(filename)
diff --git a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_meta/test_meta.py b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_meta/test_meta.py
index d26fb8c601..2af3ff9df3 100644
--- a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_meta/test_meta.py
+++ b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_meta/test_meta.py
@@ -10,7 +10,6 @@
import random
import string
-from nose.plugins.attrib import attr
from unittest import skip
from chart_studio import plotly as py
@@ -33,7 +32,6 @@ def random_filename(self):
unique_filename = "Valid Grid with Meta " + "".join(random_chars)
return unique_filename
- @attr("slow")
def test_upload_meta(self):
unique_filename = self.random_filename()
grid_url = py.grid_ops.upload(self._grid, unique_filename, auto_open=False)
@@ -41,7 +39,6 @@ def test_upload_meta(self):
# Add some Metadata to that grid
py.meta_ops.upload(self._meta, grid_url=grid_url)
- @attr("slow")
def test_upload_meta_with_grid(self):
c1 = Column([1, 2, 3, 4], "first column")
Grid([c1])
diff --git a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_plotly/test_plot.py b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_plotly/test_plot.py
index 3982bde7d8..7351f1ee2a 100644
--- a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_plotly/test_plot.py
+++ b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_plotly/test_plot.py
@@ -13,7 +13,6 @@
import json as _json
import warnings
-from nose.plugins.attrib import attr
import chart_studio.tools as tls
import plotly.tools
@@ -37,7 +36,6 @@ def setUp(self):
py.sign_in("PlotlyImageTest", "786r5mecv0")
self.simple_figure = {"data": [{"x": [1, 2, 3], "y": [2, 1, 2]}]}
- @attr("slow")
def test_plot_valid(self):
fig = {
"data": [{"x": (1, 2, 3), "y": (2, 1, 2)}],
@@ -155,7 +153,6 @@ def test_plot_option_logic_only_sharing_given(self):
}
self.assertEqual(plot_option_logic, expected_plot_option_logic)
- @attr("slow")
def test_plot_url_given_sharing_key(self):
# Give share_key is requested, the retun url should contain
@@ -175,7 +172,6 @@ def test_plot_url_given_sharing_key(self):
self.assertTrue("share_key=" in plot_url)
- @attr("slow")
def test_plot_url_response_given_sharing_key(self):
# Given share_key is requested, get request of the url should
@@ -196,7 +192,6 @@ def test_plot_url_response_given_sharing_key(self):
self.assertEqual(response.status_code, 200)
- @attr("slow")
def test_private_plot_response_with_and_without_share_key(self):
# The json file of the private plot should be 404 and once
diff --git a/packages/python/chart-studio/tox.ini b/packages/python/chart-studio/tox.ini
index 4a43598e52..faddb36305 100644
--- a/packages/python/chart-studio/tox.ini
+++ b/packages/python/chart-studio/tox.ini
@@ -24,15 +24,14 @@
; PASSING ADDITONAL ARGUMENTS TO TEST COMMANDS
; The {posargs} is tox-specific and passes in any command line args after `--`.
; For example, given the testing command in *this* file:
-; nosetests {posargs} -x plotly/tests/test_core
+; pytest {posargs} -x plotly/tests/test_core
;
; The following command:
-; tox -- -a '!slow'
+; tox -- -k 'not nodev'
;
; Tells tox to call:
-; nosetests -a '!slow' -x plotly/tests/test_core
+; pytest -k 'not nodev' -x plotly/tests/test_core
;
-; Which is a nice way to skip slow tests for faster testing cycles.
[tox]
; The py{A,B,C}-{X,Y} generates a matrix of envs:
@@ -72,16 +71,16 @@ deps=
basepython={env:PLOTLY_TOX_PYTHON_27:}
commands=
python --version
- nosetests {posargs} -x chart_studio/tests/
+ pytest {posargs} -x chart_studio/tests/
[testenv:py35-plot_ly]
basepython={env:PLOTLY_TOX_PYTHON_35:}
commands=
python --version
- nosetests {posargs} -x chart_studio/tests/
+ pytest {posargs} -x chart_studio/tests/
[testenv:py37-plot_ly]
basepython={env:PLOTLY_TOX_PYTHON_37:}
commands=
python --version
- nosetests {posargs} -x chart_studio/tests/
+ pytest {posargs} -x chart_studio/tests/
diff --git a/packages/python/plotly/optional-requirements.txt b/packages/python/plotly/optional-requirements.txt
index d0bb959e0d..9886dcd187 100644
--- a/packages/python/plotly/optional-requirements.txt
+++ b/packages/python/plotly/optional-requirements.txt
@@ -14,7 +14,6 @@ numpy
## testing dependencies ##
coverage==4.3.1
mock==2.0.0
-nose==1.3.3
pytest==3.5.1
backports.tempfile==1.0
xarray
diff --git a/packages/python/plotly/plotly/_widget_version.py b/packages/python/plotly/plotly/_widget_version.py
index d6c83d0794..ee9406e56f 100644
--- a/packages/python/plotly/plotly/_widget_version.py
+++ b/packages/python/plotly/plotly/_widget_version.py
@@ -2,4 +2,4 @@
# for automated dev builds
#
# It is edited by hand prior to official releases
-__frontend_version__ = "1.5.2"
+__frontend_version__ = "1.5.3"
diff --git a/packages/python/plotly/plotly/matplotlylib/mplexporter/tests/test_basic.py b/packages/python/plotly/plotly/matplotlylib/mplexporter/tests/test_basic.py
index 1c4dfb3e92..b86759fa18 100644
--- a/packages/python/plotly/plotly/matplotlylib/mplexporter/tests/test_basic.py
+++ b/packages/python/plotly/plotly/matplotlylib/mplexporter/tests/test_basic.py
@@ -1,7 +1,7 @@
import matplotlib
import numpy as np
from distutils.version import LooseVersion
-from nose.plugins.skip import SkipTest
+import pytest
from numpy.testing import assert_warns
from ..exporter import Exporter
@@ -168,7 +168,7 @@ def test_image():
# Test fails for matplotlib 1.5+ because the size of the image
# generated by matplotlib has changed.
if LooseVersion(matplotlib.__version__) >= LooseVersion('1.5.0'):
- raise SkipTest("Test fails for matplotlib version > 1.5.0");
+ pytest.skip("Test fails for matplotlib version > 1.5.0")
np.random.seed(0) # image size depends on the seed
fig, ax = plt.subplots(figsize=(2, 2))
ax.imshow(np.random.random((10, 10)),
diff --git a/packages/python/plotly/plotly/tests/test_core/test_colors/test_colors.py b/packages/python/plotly/plotly/tests/test_core/test_colors/test_colors.py
index 053b595e50..e382e9bfd7 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_colors/test_colors.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_colors/test_colors.py
@@ -1,6 +1,5 @@
from unittest import TestCase
-from nose.tools import raises
import plotly.tools as tls
from plotly.exceptions import PlotlyError
import plotly.colors as colors
diff --git a/packages/python/plotly/plotly/tests/test_core/test_figure_messages/test_move_delete_traces.py b/packages/python/plotly/plotly/tests/test_core/test_figure_messages/test_move_delete_traces.py
index a644cf6594..9a8e332549 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_figure_messages/test_move_delete_traces.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_figure_messages/test_move_delete_traces.py
@@ -1,6 +1,6 @@
import sys
from unittest import TestCase
-from nose.tools import raises
+import pytest
import plotly.graph_objs as go
@@ -80,12 +80,12 @@ def test_move_and_delete_traces(self):
self.figure._send_deleteTraces_msg.assert_called_once_with([1])
self.figure._send_moveTraces_msg.assert_called_once_with([0, 1], [1, 0])
- @raises(ValueError)
def test_validate_assigned_traces_are_subset(self):
traces = self.figure.data
- self.figure.data = [traces[2], go.Scatter(y=[3, 2, 1]), traces[1]]
+ with pytest.raises(ValueError):
+ self.figure.data = [traces[2], go.Scatter(y=[3, 2, 1]), traces[1]]
- @raises(ValueError)
def test_validate_assigned_traces_are_not_duplicates(self):
traces = self.figure.data
- self.figure.data = [traces[2], traces[1], traces[1]]
+ with pytest.raises(ValueError):
+ self.figure.data = [traces[2], traces[1], traces[1]]
diff --git a/packages/python/plotly/plotly/tests/test_core/test_figure_messages/test_on_change.py b/packages/python/plotly/plotly/tests/test_core/test_figure_messages/test_on_change.py
index 5f2aeb610f..8e2ce3426d 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_figure_messages/test_on_change.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_figure_messages/test_on_change.py
@@ -1,6 +1,6 @@
import sys
from unittest import TestCase
-from nose.tools import raises
+import pytest
import plotly.graph_objs as go
@@ -24,26 +24,26 @@ def setUp(self):
# on_change validation
# --------------------
- @raises(ValueError)
def test_raise_if_no_figure(self):
scatt = go.Scatter()
fn = MagicMock()
- scatt.on_change(fn, "x")
+ with pytest.raises(ValueError):
+ scatt.on_change(fn, "x")
- @raises(ValueError)
def test_raise_on_frame_hierarchy(self):
fn = MagicMock()
- self.figure.frames[0].layout.xaxis.on_change(fn, "range")
+ with pytest.raises(ValueError):
+ self.figure.frames[0].layout.xaxis.on_change(fn, "range")
- @raises(ValueError)
def test_validate_property_path_nested(self):
fn = MagicMock()
- self.figure.layout.xaxis.on_change(fn, "bogus")
+ with pytest.raises(ValueError):
+ self.figure.layout.xaxis.on_change(fn, "bogus")
- @raises(ValueError)
def test_validate_property_path_nested(self):
fn = MagicMock()
- self.figure.layout.on_change(fn, "xaxis.titlefont.bogus")
+ with pytest.raises(ValueError):
+ self.figure.layout.on_change(fn, "xaxis.titlefont.bogus")
# Python triggered changes
# ------------------------
diff --git a/packages/python/plotly/plotly/tests/test_core/test_figure_widget_backend/test_validate_no_frames.py b/packages/python/plotly/plotly/tests/test_core/test_figure_widget_backend/test_validate_no_frames.py
index d7331872e8..81f0749695 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_figure_widget_backend/test_validate_no_frames.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_figure_widget_backend/test_validate_no_frames.py
@@ -1,29 +1,29 @@
from unittest import TestCase
import plotly.graph_objs as go
-from nose.tools import raises
+import pytest
class TestNoFrames(TestCase):
if "FigureWidget" in go.__dict__.keys():
- @raises(ValueError)
def test_no_frames_in_constructor_kwarg(self):
- go.FigureWidget(frames=[{}])
+ with pytest.raises(ValueError):
+ go.FigureWidget(frames=[{}])
def test_emtpy_frames_ok_as_constructor_kwarg(self):
go.FigureWidget(frames=[])
- @raises(ValueError)
def test_no_frames_in_constructor_dict(self):
- go.FigureWidget({"frames": [{}]})
+ with pytest.raises(ValueError):
+ go.FigureWidget({"frames": [{}]})
def test_emtpy_frames_ok_as_constructor_dict_key(self):
go.FigureWidget({"frames": []})
- @raises(ValueError)
def test_no_frames_assignment(self):
fig = go.FigureWidget()
- fig.frames = [{}]
+ with pytest.raises(ValueError):
+ fig.frames = [{}]
def test_emtpy_frames_assignment_ok(self):
fig = go.FigureWidget()
diff --git a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_annotations.py b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_annotations.py
index c551bc5be1..65aff11e98 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_annotations.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_annotations.py
@@ -8,8 +8,6 @@
from __future__ import absolute_import
from unittest import skip
-from nose.tools import raises
-
from plotly.exceptions import (
PlotlyError,
PlotlyDictKeyError,
diff --git a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_append_trace.py b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_append_trace.py
index 9f52249222..f01770ceb8 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_append_trace.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_append_trace.py
@@ -1,6 +1,5 @@
from __future__ import absolute_import
-
-from nose.tools import raises
+import pytest
from plotly.graph_objs import (
Data,
@@ -19,31 +18,31 @@
import copy
-@raises(Exception)
def test_print_grid_before_make_subplots():
fig = Figure()
- fig.print_grid()
+ with pytest.raises(Exception):
+ fig.print_grid()
-@raises(Exception)
def test_append_trace_before_make_subplots():
trace = Scatter(x=[1, 2, 3], y=[2, 3, 4])
fig = Figure()
- fig.append_trace(trace, 2, 2)
+ with pytest.raises(Exception):
+ fig.append_trace(trace, 2, 2)
-@raises(Exception)
def test_append_trace_row_out_of_range():
trace = Scatter(x=[1, 2, 3], y=[2, 3, 4])
fig = tls.make_subplots(rows=2, cols=3)
- fig.append_trace(trace, 10, 2)
+ with pytest.raises(Exception):
+ fig.append_trace(trace, 10, 2)
-@raises(Exception)
def test_append_trace_col_out_of_range():
trace = Scatter(x=[1, 2, 3], y=[2, 3, 4])
fig = tls.make_subplots(rows=2, cols=3)
- fig.append_trace(trace, 2, 0)
+ with pytest.raises(Exception):
+ fig.append_trace(trace, 2, 0)
def test_append_scatter():
diff --git a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_constructor.py b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_constructor.py
index 870b11b3de..09fa78857b 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_constructor.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_constructor.py
@@ -1,6 +1,6 @@
from unittest import TestCase
import plotly.graph_objs as go
-from nose.tools import raises
+import pytest
class TestGraphObjConstructor(TestCase):
@@ -28,18 +28,18 @@ def test_kwarg_takes_precedence(self):
m.to_plotly_json(), {"color": "blue", "size": 12, "opacity": 0.6}
)
- @raises(ValueError)
def test_invalid_kwarg(self):
- go.scatter.Marker(bogus=[1, 2, 3])
+ with pytest.raises(ValueError):
+ go.scatter.Marker(bogus=[1, 2, 3])
- @raises(ValueError)
def test_invalid_arg(self):
- go.scatter.Marker([1, 2, 3])
+ with pytest.raises(ValueError):
+ go.scatter.Marker([1, 2, 3])
- @raises(ValueError)
def test_valid_arg_with_invalid_key_name(self):
- go.scatter.Marker({"bogus": 12})
+ with pytest.raises(ValueError):
+ go.scatter.Marker({"bogus": 12})
- @raises(ValueError)
def test_valid_arg_with_invalid_key_value(self):
- go.scatter.Marker({"color": "bogus"})
+ with pytest.raises(ValueError):
+ go.scatter.Marker({"color": "bogus"})
diff --git a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_data.py b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_data.py
index faec80efcd..136a043a46 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_data.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_data.py
@@ -8,7 +8,6 @@
from __future__ import absolute_import
from unittest import skip
-from nose.tools import raises
from plotly.exceptions import (
PlotlyError,
@@ -30,7 +29,6 @@ def test_trivial():
assert Data() == list()
-# @raises(PlotlyError)
def test_weird_instantiation(): # Python allows this...
assert Data({}) == []
@@ -43,26 +41,21 @@ def test_dict_instantiation():
Data([{"type": "scatter"}])
-# @raises(PlotlyDictKeyError)
def test_dict_instantiation_key_error():
assert Data([{"not-a-key": "anything"}]) == [{"not-a-key": "anything"}]
-# @raises(PlotlyDictValueError)
def test_dict_instantiation_key_error_2():
assert Data([{"marker": "not-a-dict"}]) == [{"marker": "not-a-dict"}]
-# @raises(PlotlyDataTypeError)
def test_dict_instantiation_type_error():
assert Data([{"type": "invalid_type"}]) == [{"type": "invalid_type"}]
-# @raises(PlotlyListEntryError)
def test_dict_instantiation_graph_obj_error_0():
assert Data([Data()]) == [[]]
-# raises(PlotlyListEntryError)
def test_dict_instantiation_graph_obj_error_2():
assert Data([Annotations()]) == [[]]
diff --git a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_error_bars.py b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_error_bars.py
index 7526135d15..d12abbc24c 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_error_bars.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_error_bars.py
@@ -7,7 +7,6 @@
"""
from __future__ import absolute_import
-from nose.tools import raises
from plotly.graph_objs import ErrorX, ErrorY
from plotly.exceptions import PlotlyDictKeyError
diff --git a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_figure_properties.py b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_figure_properties.py
index 26a256de9f..99ee26e0ba 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_figure_properties.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_figure_properties.py
@@ -1,6 +1,7 @@
from unittest import TestCase
+import pytest
+
import plotly.graph_objs as go
-from nose.tools import raises
import plotly.io as pio
@@ -81,21 +82,21 @@ def test_property_assignment_dots(self):
self.figure["frames[0].layout.yaxis.title.text"] = "f2"
self.assertEqual(self.figure["frames.0.layout.yaxis.title.text"], "f2")
- @raises(AttributeError)
def test_access_invalid_attr(self):
- self.figure.bogus
+ with pytest.raises(AttributeError):
+ self.figure.bogus
- @raises(KeyError)
def test_access_invalid_item(self):
- self.figure["bogus"]
+ with pytest.raises(KeyError):
+ self.figure["bogus"]
- @raises(AttributeError)
def test_assign_invalid_attr(self):
- self.figure.bogus = "val"
+ with pytest.raises(AttributeError):
+ self.figure.bogus = "val"
- @raises(KeyError)
def test_access_invalid_item(self):
- self.figure["bogus"] = "val"
+ with pytest.raises(KeyError):
+ self.figure["bogus"] = "val"
# Update
def test_update_layout(self):
@@ -202,9 +203,9 @@ def test_update_frames(self):
)
self.assertEqual(self.figure.frames[0].layout.yaxis.title.text, "f4")
- @raises(ValueError)
def test_update_invalid_attr(self):
- self.figure.layout.update({"xaxis": {"bogus": 32}})
+ with pytest.raises(ValueError):
+ self.figure.layout.update({"xaxis": {"bogus": 32}})
# plotly_restyle
def test_plotly_restyle(self):
@@ -218,13 +219,13 @@ def test_plotly_restyle(self):
self.assertEqual(self.figure.data[0].marker.color, "blue")
- @raises(ValueError)
def test_restyle_validate_property(self):
- self.figure.plotly_restyle({"bogus": 3}, trace_indexes=[0])
+ with pytest.raises(ValueError):
+ self.figure.plotly_restyle({"bogus": 3}, trace_indexes=[0])
- @raises(ValueError)
def test_restyle_validate_property_nested(self):
- self.figure.plotly_restyle({"marker.bogus": 3}, trace_indexes=[0])
+ with pytest.raises(ValueError):
+ self.figure.plotly_restyle({"marker.bogus": 3}, trace_indexes=[0])
# plotly_relayout
def test_plotly_relayout(self):
@@ -235,17 +236,17 @@ def test_plotly_relayout(self):
self.figure.plotly_relayout(relayout_data={"xaxis.range": [10, 20]})
self.assertEqual(self.figure.layout.xaxis.range, (10, 20))
- @raises(ValueError)
def test_relayout_validate_property(self):
- self.figure.plotly_relayout({"bogus": [1, 3]})
+ with pytest.raises(ValueError):
+ self.figure.plotly_relayout({"bogus": [1, 3]})
- @raises(ValueError)
def test_relayout_validate_property_nested(self):
- self.figure.plotly_relayout({"xaxis.bogus": [1, 3]})
+ with pytest.raises(ValueError):
+ self.figure.plotly_relayout({"xaxis.bogus": [1, 3]})
- @raises(ValueError)
def test_relayout_validate_unintialized_subplot(self):
- self.figure.plotly_relayout({"xaxis2.range": [1, 3]})
+ with pytest.raises(ValueError):
+ self.figure.plotly_relayout({"xaxis2.range": [1, 3]})
# plotly_update
def test_plotly_update_layout(self):
@@ -267,10 +268,10 @@ def test_plotly_update_data(self):
self.assertEqual(self.figure.data[0].marker.color, "blue")
- @raises(ValueError)
def test_plotly_update_validate_property_trace(self):
- self.figure.plotly_update(restyle_data={"bogus": 3}, trace_indexes=[0])
+ with pytest.raises(ValueError):
+ self.figure.plotly_update(restyle_data={"bogus": 3}, trace_indexes=[0])
- @raises(ValueError)
def test_plotly_update_validate_property_layout(self):
- self.figure.plotly_update(relayout_data={"xaxis.bogus": [1, 3]})
+ with pytest.raises(ValueError):
+ self.figure.plotly_update(relayout_data={"xaxis.bogus": [1, 3]})
diff --git a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_frames.py b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_frames.py
index 37a33b2026..c7dc96d8e8 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_frames.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_frames.py
@@ -4,7 +4,7 @@
from plotly.graph_objs import Bar, Frames, Frame, Layout
-from nose.plugins.attrib import attr
+import pytest
import re
@@ -43,7 +43,7 @@ def test_non_string_frame(self):
# with self.assertRaises(exceptions.PlotlyListEntryError):
# frames.append(0)
- @attr("nodev")
+ @pytest.mark.nodev
def test_deeply_nested_layout_attributes(self):
frames = Frame
frames.layout = [Layout()]
diff --git a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_layout_subplots.py b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_layout_subplots.py
index 1401512ada..037d238498 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_layout_subplots.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_layout_subplots.py
@@ -1,6 +1,7 @@
from unittest import TestCase
+import pytest
+
import plotly.graph_objs as go
-from nose.tools import raises
import plotly.io as pio
@@ -33,13 +34,13 @@ def test_initial_access_subplots(self):
self.assertIs(self.layout.mapbox, self.layout.mapbox1)
self.assertIs(self.layout.polar, self.layout.polar1)
- @raises(AttributeError)
def test_initial_access_subplot2(self):
- self.layout.xaxis2
+ with pytest.raises(AttributeError):
+ self.layout.xaxis2
- @raises(KeyError)
def test_initial_access_subplot2(self):
- self.layout["xaxis2"]
+ with pytest.raises(KeyError):
+ self.layout["xaxis2"]
def test_assign_subplots(self):
self.assertIsNone(self.layout.xaxis.title.text)
diff --git a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_properties_validated.py b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_properties_validated.py
index e31d1dad09..c3edcfb111 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_properties_validated.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_properties_validated.py
@@ -1,6 +1,6 @@
from unittest import TestCase
import plotly.graph_objs as go
-from nose.tools import raises
+import pytest
class TestPropertyValidation(TestCase):
@@ -9,43 +9,43 @@ def setUp(self):
self.scatter = go.Scatter()
self.scatter.name = "Scatter 1"
- @raises(ValueError)
def test_validators_work_attr(self):
"""
Note: all of the individual validators are tested in
`_plotly_utils/tests/validators`. Here we're just making sure that
datatypes make use of validators
"""
- self.scatter.name = [1, 2, 3]
+ with pytest.raises(ValueError):
+ self.scatter.name = [1, 2, 3]
- @raises(ValueError)
def test_validators_work_item(self):
"""
Note: all of the individual validators are tested in
`_plotly_utils/tests/validators`. Here we're just making sure that
datatypes make use of validators
"""
- self.scatter["name"] = [1, 2, 3]
+ with pytest.raises(ValueError):
+ self.scatter["name"] = [1, 2, 3]
- @raises(ValueError)
def test_invalid_attr_assignment(self):
- self.scatter.bogus = 87
+ with pytest.raises(ValueError):
+ self.scatter.bogus = 87
- @raises(ValueError)
def test_invalid_item_assignment(self):
- self.scatter["bogus"] = 87
+ with pytest.raises(ValueError):
+ self.scatter["bogus"] = 87
- @raises(ValueError)
def test_invalid_dot_assignment(self):
- self.scatter["marker.bogus"] = 87
+ with pytest.raises(ValueError):
+ self.scatter["marker.bogus"] = 87
- @raises(ValueError)
def test_invalid_tuple_assignment(self):
- self.scatter[("marker", "bogus")] = 87
+ with pytest.raises(ValueError):
+ self.scatter[("marker", "bogus")] = 87
- @raises(ValueError)
def test_invalid_constructor_kwarg(self):
- go.Scatter(bogus=87)
+ with pytest.raises(ValueError):
+ go.Scatter(bogus=87)
class TestPropertyPresentation(TestCase):
diff --git a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_scatter.py b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_scatter.py
index d3af52db2a..78d3aa1d77 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_scatter.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_scatter.py
@@ -7,7 +7,6 @@
"""
from __future__ import absolute_import
-from nose.tools import raises
from plotly.graph_objs import Scatter
from plotly.exceptions import PlotlyError
diff --git a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_template.py b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_template.py
index 47bbf12b06..8010e962a9 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_template.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_template.py
@@ -2,7 +2,7 @@
import copy
from unittest import TestCase
-from nose.tools import raises
+import pytest
import plotly.io as pio
import plotly.graph_objs as go
@@ -105,27 +105,31 @@ def test_defaults_in_property_assignment(self):
},
)
- @raises(ValueError)
def test_invalid_defaults_property_name_constructor(self):
- go.Figure(layout={"template": {"layout": {"imagedefaults": {"bogus": 500}}}})
+ with pytest.raises(ValueError):
+ go.Figure(
+ layout={"template": {"layout": {"imagedefaults": {"bogus": 500}}}}
+ )
- @raises(ValueError)
def test_invalid_defaults_property_value_constructor(self):
- go.Figure(
- layout={
- "template": {"layout": {"imagedefaults": {"sizex": "str not number"}}}
- }
- )
+ with pytest.raises(ValueError):
+ go.Figure(
+ layout={
+ "template": {
+ "layout": {"imagedefaults": {"sizex": "str not number"}}
+ }
+ }
+ )
- @raises(ValueError)
def test_invalid_defaults_property_name_constructor(self):
- go.Figure(layout={"template": {"layout": {"xaxis": {"bogus": 500}}}})
+ with pytest.raises(ValueError):
+ go.Figure(layout={"template": {"layout": {"xaxis": {"bogus": 500}}}})
- @raises(ValueError)
def test_invalid_defaults_property_value_constructor(self):
- go.Figure(
- layout={"template": {"layout": {"xaxis": {"range": "str not tuple"}}}}
- )
+ with pytest.raises(ValueError):
+ go.Figure(
+ layout={"template": {"layout": {"xaxis": {"range": "str not tuple"}}}}
+ )
# plotly.io.template tests
# ------------------------
diff --git a/packages/python/plotly/plotly/tests/test_core/test_offline/test_offline.py b/packages/python/plotly/plotly/tests/test_core/test_offline/test_offline.py
index b922d4f5ec..315a81b941 100644
--- a/packages/python/plotly/plotly/tests/test_core/test_offline/test_offline.py
+++ b/packages/python/plotly/plotly/tests/test_core/test_offline/test_offline.py
@@ -6,8 +6,8 @@
import os
from unittest import TestCase
+import pytest
-from nose.plugins.attrib import attr
import json as _json
import plotly
@@ -314,7 +314,7 @@ def get_html():
self.assertIn('"bogus": 42', html)
- @attr("nodev")
+ @pytest.mark.nodev
def test_plotlyjs_version(self):
path = os.path.join(packages_root, "javascript", "plotlywidget", "package.json")
with open(path, "rt") as f:
diff --git a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_annotations.py b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_annotations.py
index 6d0b337cd7..18d8fb7c4b 100644
--- a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_annotations.py
+++ b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_annotations.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import
-from nose.plugins.attrib import attr
+import pytest
from plotly import optional_imports
@@ -14,7 +14,7 @@
from plotly.tests.test_optional.test_matplotlylib.data.annotations import *
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_annotations():
fig, ax = plt.subplots()
ax.plot([1, 2, 3], "b-")
diff --git a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_axis_scales.py b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_axis_scales.py
index 9063ce7319..e7f0753da3 100644
--- a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_axis_scales.py
+++ b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_axis_scales.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import
-from nose.plugins.attrib import attr
+import pytest
from plotly import optional_imports
from plotly.tests.utils import compare_dict, strip_dict_params
@@ -13,7 +13,7 @@
import matplotlib.pyplot as plt
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_even_linear_scale():
fig, ax = plt.subplots()
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
diff --git a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_bars.py b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_bars.py
index 6a6df89615..40d891b941 100644
--- a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_bars.py
+++ b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_bars.py
@@ -1,6 +1,5 @@
from __future__ import absolute_import
-
-from nose.plugins.attrib import attr
+import pytest
from plotly import optional_imports
from plotly.tests.utils import compare_dict, strip_dict_params
@@ -13,7 +12,7 @@
import matplotlib.pyplot as plt
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_vertical_bar():
fig, ax = plt.subplots()
ax.bar(left=D["left"], height=D["height"])
@@ -33,7 +32,7 @@ def test_vertical_bar():
assert equivalent, msg
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_horizontal_bar():
fig, ax = plt.subplots()
ax.barh(bottom=D["bottom"], width=D["width"])
@@ -53,7 +52,7 @@ def test_horizontal_bar():
assert equivalent, msg
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_h_and_v_bars():
fig, ax = plt.subplots()
ax.bar(
diff --git a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_data.py b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_data.py
index 050432c898..fc208573b5 100644
--- a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_data.py
+++ b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_data.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import
-from nose.plugins.attrib import attr
+import pytest
from plotly import optional_imports
from plotly.tests.test_optional.optional_utils import run_fig
@@ -12,7 +12,7 @@
import matplotlib.pyplot as plt
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_line_data():
fig, ax = plt.subplots()
ax.plot(D["x1"], D["y1"])
@@ -31,7 +31,7 @@ def test_line_data():
)
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_lines_data():
fig, ax = plt.subplots()
ax.plot(D["x1"], D["y1"])
@@ -63,7 +63,7 @@ def test_lines_data():
)
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_bar_data():
fig, ax = plt.subplots()
ax.bar(D["x1"], D["y1"])
@@ -74,7 +74,7 @@ def test_bar_data():
)
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_bars_data():
fig, ax = plt.subplots()
ax.bar(D["x1"], D["y1"], color="r")
diff --git a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_date_times.py b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_date_times.py
index ac4ee079e3..68546749eb 100644
--- a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_date_times.py
+++ b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_date_times.py
@@ -3,9 +3,9 @@
import datetime
import random
from unittest import TestCase
+import pytest
import pandas as pd
-from nose.plugins.attrib import attr
import plotly.tools as tls
from plotly import optional_imports
@@ -17,7 +17,7 @@
import matplotlib.pyplot as plt
-@attr("matplotlib")
+@pytest.mark.matplotlib
class TestDateTimes(TestCase):
def test_normal_mpl_dates(self):
datetime_format = "%Y-%m-%d %H:%M:%S"
diff --git a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_lines.py b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_lines.py
index 642936aed1..bb69c18ecc 100644
--- a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_lines.py
+++ b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_lines.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import
-from nose.plugins.attrib import attr
+import pytest
from plotly import optional_imports
from plotly.tests.utils import compare_dict, strip_dict_params
@@ -13,7 +13,7 @@
import matplotlib.pyplot as plt
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_simple_line():
fig, ax = plt.subplots()
ax.plot(D["x1"], D["y1"], label="simple")
@@ -29,7 +29,7 @@ def test_simple_line():
assert equivalent, msg
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_complicated_line():
fig, ax = plt.subplots()
ax.plot(D["x1"], D["y1"], "ro", markersize=10, alpha=0.5, label="one")
diff --git a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_scatter.py b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_scatter.py
index 839880dc59..96984130d8 100644
--- a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_scatter.py
+++ b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_scatter.py
@@ -1,6 +1,5 @@
from __future__ import absolute_import
-
-from nose.plugins.attrib import attr
+import pytest
from plotly import optional_imports
from plotly.tests.utils import compare_dict, strip_dict_params
@@ -13,7 +12,7 @@
import matplotlib.pyplot as plt
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_simple_scatter():
fig, ax = plt.subplots()
ax.scatter(D["x1"], D["y1"])
@@ -33,7 +32,7 @@ def test_simple_scatter():
assert equivalent, msg
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_double_scatter():
fig, ax = plt.subplots()
ax.scatter(D["x1"], D["y1"], color="red", s=121, marker="^", alpha=0.5)
diff --git a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_subplots.py b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_subplots.py
index 4553eadeb4..6d4e0959dd 100644
--- a/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_subplots.py
+++ b/packages/python/plotly/plotly/tests/test_optional/test_matplotlylib/test_subplots.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import
-from nose.plugins.attrib import attr
+import pytest
from plotly import optional_imports
from plotly.tests.utils import compare_dict, strip_dict_params
@@ -14,7 +14,7 @@
import matplotlib.pyplot as plt
-@attr("matplotlib")
+@pytest.mark.matplotlib
def test_blank_subplots():
fig = plt.figure()
gs = GridSpec(4, 6)
diff --git a/packages/python/plotly/plotly/tests/test_optional/test_offline/test_offline.py b/packages/python/plotly/plotly/tests/test_optional/test_offline/test_offline.py
index f16575d7c2..d36934d1ea 100644
--- a/packages/python/plotly/plotly/tests/test_optional/test_offline/test_offline.py
+++ b/packages/python/plotly/plotly/tests/test_optional/test_offline/test_offline.py
@@ -4,11 +4,10 @@
"""
from __future__ import absolute_import
import re
-from nose.tools import raises
-from nose.plugins.attrib import attr
import json as _json
from unittest import TestCase
+import pytest
import plotly
from plotly import optional_imports
@@ -39,7 +38,7 @@ def test_iplot_works_after_you_call_init_notebook_mode(self):
if matplotlylib:
- @attr("matplotlib")
+ @pytest.mark.matplotlib
def test_iplot_mpl_works(self):
# Generate matplotlib plot for tests
fig = plt.figure()
@@ -64,7 +63,7 @@ def _read_html(self, file_url):
if matplotlylib:
- @attr("matplotlib")
+ @pytest.mark.matplotlib
def test_default_mpl_plot_generates_expected_html(self):
# Generate matplotlib plot for tests
fig = plt.figure()
diff --git a/packages/python/plotly/plotly/tests/test_optional/test_utils/test_utils.py b/packages/python/plotly/plotly/tests/test_optional/test_utils/test_utils.py
index d26e7ac6ce..24d3702491 100644
--- a/packages/python/plotly/plotly/tests/test_optional/test_utils/test_utils.py
+++ b/packages/python/plotly/plotly/tests/test_optional/test_utils/test_utils.py
@@ -9,11 +9,11 @@
import decimal
from datetime import datetime as dt
from unittest import TestCase
+import pytest
import numpy as np
import pandas as pd
import pytz
-from nose.plugins.attrib import attr
from pandas.util.testing import assert_series_equal
import json as _json
import os
@@ -295,7 +295,7 @@ def test_pil_image_encoding(self):
if matplotlylib:
- @attr("matplotlib")
+ @pytest.mark.matplotlib
def test_masked_constants_example():
# example from: https://gist.github.com/tschaume/d123d56bf586276adb98
data = {
diff --git a/packages/python/plotly/plotlywidget/static/index.js b/packages/python/plotly/plotlywidget/static/index.js
index bf3598331e..edab9e72d2 100644
--- a/packages/python/plotly/plotlywidget/static/index.js
+++ b/packages/python/plotly/plotlywidget/static/index.js
@@ -94,7 +94,7 @@ module.exports = g;
/* 1 */
/***/ (function(module, exports) {
-module.exports = {"name":"plotlywidget","version":"1.5.2","description":"The plotly JupyterLab extension","author":"The plotly.py team","license":"MIT","main":"src/index.js","repository":{"type":"git","url":"https://github.com/plotly/plotly.py"},"keywords":["jupyter","widgets","ipython","ipywidgets","plotly"],"files":["src/**/*.js","dist/*.js","style/*.*"],"scripts":{"build":"webpack","clean":"rimraf dist/ && rimraf ../../python/plotly/plotlywidget/static'","test":"echo \"Error: no test specified\" && exit 1"},"devDependencies":{"webpack":"^3.10.0","rimraf":"^2.6.1","ify-loader":"^1.1.0","typescript":"~3.1.1"},"dependencies":{"plotly.js":"^1.52.2","@jupyter-widgets/base":"^2.0.0","lodash":"^4.17.4"},"jupyterlab":{"extension":"src/jupyterlab-plugin.js"}}
+module.exports = {"name":"plotlywidget","version":"1.5.3","description":"The plotly JupyterLab extension","author":"The plotly.py team","license":"MIT","main":"src/index.js","repository":{"type":"git","url":"https://github.com/plotly/plotly.py"},"keywords":["jupyter","widgets","ipython","ipywidgets","plotly"],"files":["src/**/*.js","dist/*.js","style/*.*"],"scripts":{"build":"webpack","clean":"rimraf dist/ && rimraf ../../python/plotly/plotlywidget/static'","test":"echo \"Error: no test specified\" && exit 1"},"devDependencies":{"webpack":"^3.10.0","rimraf":"^2.6.1","ify-loader":"^1.1.0","typescript":"~3.1.1"},"dependencies":{"plotly.js":"^1.52.2","@jupyter-widgets/base":"^2.0.0","lodash":"^4.17.4"},"jupyterlab":{"extension":"src/jupyterlab-plugin.js"}}
/***/ }),
/* 2 */
diff --git a/packages/python/plotly/pytest.ini b/packages/python/plotly/pytest.ini
new file mode 100644
index 0000000000..3d05496c99
--- /dev/null
+++ b/packages/python/plotly/pytest.ini
@@ -0,0 +1,5 @@
+# content of pytest.ini
+[pytest]
+markers =
+ nodev: mark a test as nodev
+ matplotlib: mark a test as matplotlib
diff --git a/packages/python/plotly/tox.ini b/packages/python/plotly/tox.ini
index df41b7e1df..b1f1cca2f7 100644
--- a/packages/python/plotly/tox.ini
+++ b/packages/python/plotly/tox.ini
@@ -24,15 +24,14 @@
; PASSING ADDITONAL ARGUMENTS TO TEST COMMANDS
; The {posargs} is tox-specific and passes in any command line args after `--`.
; For example, given the testing command in *this* file:
-; nosetests {posargs} -x plotly/tests/test_core
+; pytest {posargs} -x plotly/tests/test_core
;
; The following command:
-; tox -- -a '!slow'
+; tox -- -k 'not nodev'
;
; Tells tox to call:
-; nosetests -a '!slow' -x plotly/tests/test_core
+; pytest -k 'not nodev' -x plotly/tests/test_core
;
-; Which is a nice way to skip slow tests for faster testing cycles.
[tox]
; The py{A,B,C}-{X,Y} generates a matrix of envs:
@@ -53,7 +52,6 @@ deps=
coverage==4.3.1
decorator==4.0.9
mock==2.0.0
- nose==1.3.7
requests==2.12.4
six==1.10.0
pytz==2016.10
@@ -81,25 +79,25 @@ deps=
basepython={env:PLOTLY_TOX_PYTHON_27:}
commands=
python --version
- nosetests {posargs} -x plotly/tests/test_core
+ pytest {posargs} -x plotly/tests/test_core
[testenv:py35-core]
basepython={env:PLOTLY_TOX_PYTHON_35:}
commands=
python --version
- nosetests {posargs} -x plotly/tests/test_core
+ pytest {posargs} -x plotly/tests/test_core
[testenv:py36-core]
basepython={env:PLOTLY_TOX_PYTHON_36:}
commands=
python --version
- nosetests {posargs} -x plotly/tests/test_core
+ pytest {posargs} -x plotly/tests/test_core
[testenv:py37-core]
basepython={env:PLOTLY_TOX_PYTHON_37:}
commands=
python --version
- nosetests {posargs} -x plotly/tests/test_core
+ pytest {posargs} -x plotly/tests/test_core
; OPTIONAL ENVIRONMENTS
;[testenv:py27-optional]
@@ -116,8 +114,8 @@ commands=
basepython={env:PLOTLY_TOX_PYTHON_27:}
commands=
python --version
- nosetests {posargs} -x plotly/tests/test_core
- nosetests {posargs} -x plotly/tests/test_optional
+ pytest {posargs} -x plotly/tests/test_core
+ pytest {posargs} -x plotly/tests/test_optional
pytest _plotly_utils/tests/
pytest plotly/tests/test_io
@@ -125,8 +123,8 @@ commands=
basepython={env:PLOTLY_TOX_PYTHON_35:}
commands=
python --version
- nosetests {posargs} -x plotly/tests/test_core
- nosetests {posargs} -x plotly/tests/test_optional
+ pytest {posargs} -x plotly/tests/test_core
+ pytest {posargs} -x plotly/tests/test_optional
pytest _plotly_utils/tests/
pytest plotly/tests/test_io
@@ -134,8 +132,8 @@ commands=
basepython={env:PLOTLY_TOX_PYTHON_36:}
commands=
python --version
- nosetests {posargs} -x plotly/tests/test_core
- nosetests {posargs} -x plotly/tests/test_optional
+ pytest {posargs} -x plotly/tests/test_core
+ pytest {posargs} -x plotly/tests/test_optional
pytest _plotly_utils/tests/
pytest plotly/tests/test_io
@@ -143,7 +141,7 @@ commands=
basepython={env:PLOTLY_TOX_PYTHON_37:}
commands=
python --version
- nosetests {posargs} -x plotly/tests/test_core
- nosetests {posargs} -x plotly/tests/test_optional
+ pytest {posargs} -x plotly/tests/test_core
+ pytest {posargs} -x plotly/tests/test_optional
pytest _plotly_utils/tests/
pytest plotly/tests/test_io