The bottom line. Follow your Nose, or our Nose. Write-run-love tests ✊.
Check out the Code of Conduct. Don't tl:dr; it, but the general idea is to be nice.
Open an issue! Go to https://github.com/plotly/plotly.py/issues. It's possible that your issue was already addressed. If it wasn't, open it. We also accept PRs; take a look at the steps below for instructions on how to do this.
Check out our Support App: https://support.plot.ly/libraries/python or Community Forum: https://community.plot.ly/.
First, you'll need to get our project. This is the appropriate clone command (if you're unfamiliar with this process, https://help.github.com/articles/fork-a-repo):
DO THIS (in the directory where you want the repo to live)
git clone https://github.com/your_github_username/plotly.py.git
Second, this project uses git submodules! They're both helpful and, at times, difficult to work with. The good news is you probably don't need to think about them! Just run the following shell command to make sure that your local repo is wired properly:
DO THIS (run this command in your new plotly.py
directory)
make setup_subs
That's going to initialize the submodules we use in this project, update them so that they're synced to the proper commit, and copy files to the appropriate locations in your local repo.
Here's what you need to know: changes to any files inside the following directories will get overwritten. These are synced with the submodules, if you need to change functionality there, you will need to make a pull request in the appropriate sub project repository.
- chunked_requests
- graph_reference
- mplexporter
Additionally, there are some project shortcuts that live in the makefile
file. You can read all about this in the make_instructions.txt
file. OR, just run:
make readme
Third, don't work in the master
branch. As soon as you get your master branch ready, run:
DO THIS (but change the branch name)
git checkout -b my-dev-branch
... where you should give your branch a more descriptive name than my-dev-branch
Once you've made your changes (and hopefully written some tests...), make that pull request!
Setting up Python versions that don't require you to use sudo
is a good idea. In addition, the core Python on your machine may not be the Python that we've developed in! Here are some nice guides for Mac, Windows, and Linux:
- http://docs.python-guide.org/en/latest/starting/install/osx/
- http://docs.python-guide.org/en/latest/starting/install/win/
- http://docs.python-guide.org/en/latest/starting/install/linux/
Virtualenv is a way to create Python environments on your machine that know nothing about one another. This is really helpful for ironing out dependency-problems arising from different versions of packages. Here's a nice guide on how to do this: http://docs.python-guide.org/en/latest/dev/virtualenvs/
The PYTHONPATH variable in your shell tells Python where to look for modules. Since you'll be developing, it'll be a pain to need to install Python every time you need to test some functionality (or at least ensure you're running code from the right directory...). You can easily make this change from a shell:
export PYTHONPATH="/path/to/local/repo:$PYTHONPATH"
Note, that's non-permanent. When you close the shell, that variable definition disappears. Also, path/to/local/repo
is your specific repository path (e.g., /Users/andrew/projects/python-api
).
Now you can run the following code and be guaranteed to have a working development version that you can make changes to on-the-fly, test, and be confident will not break on other's machines!
pip install -r requirements.txt
pip install -r optional-requirements.txt
export PYTHONPATH="/path/to/local/repo:$PYTHONPATH"
There's a short list of core dependencies you'll need installed in your Python environment to have any sort of fun with Plotly's Python API (see requirements.txt
). Additionally, you're likely to have even more fun if you install some other requirements (see optional-requirements.txt
).
If you decided to follow the suggestion about the Virtualenv and you've run source bin/activate
within your new virtualenv directory to activate it--you can run the following to install the core dependencies:
pip install -r requirements.txt
To install the optional dependencies:
pip install -r optional-requirements.txt
$ jupyter nbextension enable --py widgetsnbextension
$ jupyter nbextension install --py --symlink --sys-prefix plotlywidget
$ jupyter nbextension enable --py --sys-prefix plotlywidget
First update the version of the plotly.js
dependency in js/package.json
.
Then run the updateplotlyjs
command with:
$ python setup.py updateplotlyjs
This will download new versions of plot-schema.json
and plotly.min.js
from
the plotly/plotly.js
GitHub repository (and place them in
plotly/package_data
). It will then regenerate all of the graph_objs
classes based on the new schema.
We take advantage of two tools to run tests:
tox
, which is both a virtualenv management and test tool.nose
, which is is an extension of Python's unittest
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!
nosetests -w plotly/tests
Or for more verbose output:
nosetests -w plotly/tests -v
Either of those will run every test we've written for the Python API. You can get more granular by running something like:
nosetests -w plotly/tests/test_plotly
... or even more granular by running something like:
nosetests plotly/tests/test_plotly/test_plot.py
Running tests with tox is much more powerful, but requires a bit more setup.
You'll need to export an environment variable for each tox environment you wish to test with. For example, if you want to test with Python 2.7
and
Python 3.4
, but only care to check the core
specs, you would need to ensure that the following variables are exported:
export PLOTLY_TOX_PYTHON_27=<python binary>
export PLOTLY_TOX_PYTHON_34=<python binary>
Where the <python binary
is going to be specific to your development setup. As a more complete example, you might have this loaded in a .bash_profile
(or equivalent shell loader):
############
# tox envs #
############
export PLOTLY_TOX_PYTHON_27=python2.7
export PLOTLY_TOX_PYTHON_34=python3.4
export TOXENV=py27-core,py34-core
Where TOXENV
is the environment list you want to use when invoking tox
from the command line. Note that the PLOTLY_TOX_*
pattern is used to pass in variables for use in the tox.ini
file. Though this is a little setup, intensive, you'll get the following benefits:
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 bothPython 2
andPython 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:
tox -- -a '!slow'
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:
tox -- -a '!slow','!matplotlib'
You're strongly encouraged to write tests that check your added functionality.
When you write a new test anywhere under the tests
directory, if your PR gets accepted, that test will run in a virtual machine to ensure that future changes don't break your contributions!
Test accounts include: PythonTest
, PlotlyImageTest
, and PlotlyStageTest
.
This is the release process for releasing plotly.py
version X.Y.Z
with
plotlywidget
version A.B.C
.
Note: The plotlywidget
instructions must be followed if any change
has been made in the js/
directory source code, OR if the version of
plotly.js has been updated. If neither of these is the case, there's no need
to increment the plotlywidget
version or to publish a new version to npm.
After all of the functionality for the release has been merged into master,
create a branch named release_X.Y.Z
. This branch will become the
final version
Next increment the version of plotly.py
to X.Y.Zrc1
, and the version of
plotlywidget
to A.B.C-rc.1
. In both cases rc
is the semantic versioning
code for Release Candidate. The number 1 means that this is the first release
candidate, this number can be incremented if we need to publish multiple
release candidates. Note that the npm
suffix is -rc.1
and the PyPI
suffix is rc1
.
plotly/version.py
:- Update
__version__
toX.Y.Zrc1
- Update
__frontend_version__
to^A.B.C-rc.1
(Note the^
prefix)
- Update
js/package.json
- Update
"version"
toA.B.C-rc.1
- Update
Publishing plotly.py
and plotlywidget
as release candidates
allows us to go through the publication process, and test that the
installed packages work properly before general users will get them by
default. It also gives us the opportunity to ask specific users to test
that their bug reports are in fact resolved before we pull the trigger
on the official release.
Review the contents of CHANGELOG.md
. We try to follow the
keepachangelog guidelines. Make sure
the changelog includes the version being published at the top, along with the
expected publication date.
Use the Added
, Changed
, Deprecated
, Removed
, Fixed
, and Security
labels for all changes to plotly.py. If the version of plotly.js has
been updated, include this as the first Updated
entry. Call out any
noteable changes as sub-bullets (new trace types in particular), and provide
a link to the plotly.js CHANGELOG.
As the first entry in the changelog, include a JupyterLab Versions
section.
Here, document the versions of plotlywidget
,
@jupyter-widgets/jupyterlab-manager
, jupyterlab
, and
@jupyterlab/plotly-extension
that are known to be compatible with this
version of plotly.py
.
Note: Use the official (not release candidate) versions in the CHANGELOG.
Update the installation instructions in the README to the new versions of all
of the dependencies. Use the release candidate versions, this way we can point
people to the README of the release_X.Y.Z
as the instructions for trying out
the release candidate.
To upload to PyPI you'll also need to have twine
installed:
(plotly.py) $ pip install twine
And, you'll need the credentials file ~/.pypirc
. Request access from
@theengineear and @chriddyp. Then, from inside the repository:
(plotly.py) $ git checkout release_X.Y.Z
(plotly.py) $ git stash
(plotly.py) $ python setup.py sdist
(plotly.py) $ twine upload dist/plotly-X.Y.Zrc1*
Now, publish the release candidate of the plotlywidget
NPM package.
cd ./js
npm publish --access public --tag next
The --tag next
part ensures that users won't install this version unless
they explicitly ask for the version or for the version wtih the next
tag.
Create a fresh virtual environment (or conda environment) and install
the release candidate by following the new README.md
instructions,
replacing X.Y.Z
with X.Y.Zrc1
and A.B.C
with A.B.C-rc.1
.
In particular
pip install plotly==X.Y.Z
->pip install plotly==X.Y.Zrc1
jupyter labextension install [email protected]
->jupyter labextension install [email protected]
Run through the example notebooks at
https://github.com/jonmmease/plotly_ipywidget_notebooks using the classic
notebook and JupyterLab. Make sure FigureWidget
objects are displayed as
plotly figures, and make sure the in-place updates and callbacks work.
If appropriate, ask users who have submitted bug reports or feature requests that are resolved in this version to try out the release candidate.
If problems are found in the release candidate, fix them on the release branch and then publish another release candidate with the candidate number incremented.
When no problems are identified in the release candidate, remove the release candidate suffix from the following version strings:
plotly/version.py
:- Update
__version__
toX.Y.Z
- Update
__frontend_version__
to^A.B.C
(Note the^
prefix)
- Update
js/package.json
- Update
"version"
toA.B.C
- Update
Make sure the integration tests are passing on the release branch, then merge it into master on GitHub.
Update your local master, tag this merge commit as vX.Y.Z
(e.g. v3.1.1
), and push the tag.
(plotly.py) $ git checkout master
(plotly.py) $ git stash
(plotly.py) $ git pull origin master
(plotly.py) $ git tag vX.Y.Z
(plotly.py) $ git push origin vX.Y.Z
Publish the final version to PyPI
(plotly.py) $ python setup.py sdist bdist_wheel
(plotly.py) $ twine upload dist/plotly-X.Y.Z*
After it has uploaded, move to another environment and double+triple check that you are able to upgrade ok:
$ pip install plotly --upgrade
And ask one of your friends to do it too. Our tests should catch any issues, but you never know.
<3 Team Plotly
Finally, publish the final version of the widget library to npm with:
cd ./js
npm publish --access public
After publishing to PyPI, update the set version
number to match the PyPI
version.
Compute the new SHA256 hash from the sdist
package in the local
dist/
directory.
$ shasum -a 256 dist/plotly-X.Y.Z.tar.gz
cd301fff6...
Make sure you have the conda-build
and anaconda-client
packages installed
and then perform the conda build.
$ conda build recipe/
When conda-build returns successfully it will display the path to the new package.
Next run anaconda login
and enter the credentials for the plotly anaconda
channel.
Then run anaconda upload /path/to/plotly-X.Y.Z.tar.bz2
Run anaconda logout
Post a simple announcement to the Plotly Python forum, with links to the README installation instructions and to the CHANGELOG.
If you are interested in contributing to the ever-growing Plotly figure factory library in Python, check out the documentation to learn how.