diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
new file mode 100644
index 00000000000..ce8c4d00c3f
--- /dev/null
+++ b/.github/CONTRIBUTING.md
@@ -0,0 +1,42 @@
+# Contributing to xarray
+
+## Usage questions
+
+The best places to submit questions about how to use xarray are
+[Stack Overflow](https://stackoverflow.com/questions/tagged/python-xarray) and
+the [xarray Google group](https://groups.google.com/forum/#!forum/xarray).
+
+## Reporting issues
+
+When reporting issues please include as much detail as possible about your
+operating system, xarray version and python version. Whenever possible, please
+also include a brief, self-contained code example that demonstrates the problem.
+
+## Contributing code
+
+Thanks for your interest in contributing code to xarray!
+
+- If you are new to Git or Github, please take a minute to read through a few tutorials
+ on [Git](https://git-scm.com/docs/gittutorial) and [GitHub](https://guides.github.com/).
+- The basic workflow for contributing to xarray is:
+ 1. [Fork](https://help.github.com/articles/fork-a-repo/) the xarray repository
+ 2. [Clone](https://help.github.com/articles/cloning-a-repository/) the xarray repository to create a local copy on your computer:
+ ```
+ git clone git@github.com:${user}/xarray.git
+ cd xarray
+ ```
+ 3. Create a branch for your changes
+ ```
+ git checkout -b name-of-your-branch
+ ```
+ 4. Make change to your local copy of the xarray repository
+ 5. Commit those changes
+ ```
+ git add file1 file2 file3
+ git commit -m 'a descriptive commit message'
+ ```
+ 6. Push your updated branch to your fork
+ ```
+ git push origin name-of-your-branch
+ ```
+ 7. [Open a pull request](https://help.github.com/articles/creating-a-pull-request/) to the pydata/xarray repository.
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 00000000000..d10e857c4ed
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,18 @@
+#### Code Sample, a copy-pastable example if possible
+
+```python
+# Your code here
+
+```
+#### Problem description
+
+[this should explain **why** the current behavior is a problem and why the expected output is a better solution.]
+
+#### Expected Output
+
+#### Output of ``xr.show_versions()``
+
+
+# Paste the output here xr.show_versions() here
+
+
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index b74fb3000f8..320f9a9f5eb 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,4 +1,4 @@
- [ ] Closes #xxxx
- [ ] Tests added / passed
- - [ ] Passes ``git diff upstream/master | flake8 --diff``
+ - [ ] Passes ``git diff upstream/master **/*py | flake8 --diff``
- [ ] Fully documented, including `whats-new.rst` for all changes and `api.rst` for new API
diff --git a/.travis.yml b/.travis.yml
index 7b27987fc97..1dc0cb9b207 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -86,9 +86,11 @@ install:
- source activate test_env
- conda list
- python setup.py install
+ - python xarray/util/print_versions.py
script:
- py.test xarray --cov=xarray --cov-config ci/.coveragerc --cov-report term-missing --verbose $EXTRA_FLAGS
+ - git diff upstream/master **/*py | flake8 --diff --exit-zero || true
after_success:
- coveralls
diff --git a/appveyor.yml b/appveyor.yml
index 1d539821f13..b816374e6e0 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -31,15 +31,12 @@ install:
# the parent CMD process).
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
- # Check that we have the expected version and architecture for Python
- - "python --version"
- - "python -c \"import struct; print(struct.calcsize('P') * 8)\""
-
# install xarray and dependencies
- "conda env create --file ./ci/requirements-%CONDA_ENV%.yml"
- "activate test_env"
- "conda list"
- "python setup.py install"
+ - "python xarray/util/print_versions.py"
build: false
diff --git a/ci/requirements-py27-cdat+pynio.yml b/ci/requirements-py27-cdat+pynio.yml
index ccd3fbf9cb4..126dd416509 100644
--- a/ci/requirements-py27-cdat+pynio.yml
+++ b/ci/requirements-py27-cdat+pynio.yml
@@ -16,6 +16,7 @@ dependencies:
- pathlib2
- pynio
- pytest
+ - flake8
- mock
- scipy
- seaborn
diff --git a/ci/requirements-py27-min.yml b/ci/requirements-py27-min.yml
index 6f63315db67..50f6724ec51 100644
--- a/ci/requirements-py27-min.yml
+++ b/ci/requirements-py27-min.yml
@@ -2,6 +2,7 @@ name: test_env
dependencies:
- python=2.7
- pytest
+ - flake8
- mock
- numpy==1.11
- pandas==0.18.0
diff --git a/ci/requirements-py27-windows.yml b/ci/requirements-py27-windows.yml
index 73baca68dfa..bb76afd60c9 100644
--- a/ci/requirements-py27-windows.yml
+++ b/ci/requirements-py27-windows.yml
@@ -11,6 +11,7 @@ dependencies:
- netcdf4
- pathlib2
- pytest
+ - flake8
- mock
- numpy
- pandas
diff --git a/ci/requirements-py34.yml b/ci/requirements-py34.yml
index a49611751ca..0b0d4099e3b 100644
--- a/ci/requirements-py34.yml
+++ b/ci/requirements-py34.yml
@@ -3,6 +3,7 @@ dependencies:
- python=3.4
- bottleneck
- pytest
+ - flake8
- pandas
- pip:
- coveralls
diff --git a/ci/requirements-py35.yml b/ci/requirements-py35.yml
index 1c7a4558c91..8c5ca993541 100644
--- a/ci/requirements-py35.yml
+++ b/ci/requirements-py35.yml
@@ -10,6 +10,7 @@ dependencies:
- matplotlib
- netcdf4
- pytest
+ - flake8
- numpy
- pandas
- scipy
diff --git a/ci/requirements-py36-bottleneck-dev.yml b/ci/requirements-py36-bottleneck-dev.yml
index 8e2fd98cfcf..571a2e1294f 100644
--- a/ci/requirements-py36-bottleneck-dev.yml
+++ b/ci/requirements-py36-bottleneck-dev.yml
@@ -10,6 +10,7 @@ dependencies:
- matplotlib
- netcdf4
- pytest
+ - flake8
- numpy
- pandas
- scipy
diff --git a/ci/requirements-py36-condaforge-rc.yml b/ci/requirements-py36-condaforge-rc.yml
index 8426ca2df42..6519d0d0f47 100644
--- a/ci/requirements-py36-condaforge-rc.yml
+++ b/ci/requirements-py36-condaforge-rc.yml
@@ -11,6 +11,7 @@ dependencies:
- matplotlib
- netcdf4
- pytest
+ - flake8
- numpy
- pandas
- seaborn
diff --git a/ci/requirements-py36-dask-dev.yml b/ci/requirements-py36-dask-dev.yml
index 8606e15d614..ae359a13356 100644
--- a/ci/requirements-py36-dask-dev.yml
+++ b/ci/requirements-py36-dask-dev.yml
@@ -8,6 +8,7 @@ dependencies:
- matplotlib
- netcdf4
- pytest
+ - flake8
- numpy
- pandas
- seaborn
diff --git a/ci/requirements-py36-netcdf4-dev.yml b/ci/requirements-py36-netcdf4-dev.yml
index 033d1f41b4d..2daa02756bb 100644
--- a/ci/requirements-py36-netcdf4-dev.yml
+++ b/ci/requirements-py36-netcdf4-dev.yml
@@ -10,6 +10,7 @@ dependencies:
- h5netcdf
- matplotlib
- pytest
+ - flake8
- numpy
- pandas
- scipy
diff --git a/ci/requirements-py36-pandas-dev.yml b/ci/requirements-py36-pandas-dev.yml
index ebcec868f76..fe4eb226204 100644
--- a/ci/requirements-py36-pandas-dev.yml
+++ b/ci/requirements-py36-pandas-dev.yml
@@ -11,6 +11,7 @@ dependencies:
- matplotlib
- netcdf4
- pytest
+ - flake8
- numpy
- scipy
- toolz
diff --git a/ci/requirements-py36.yml b/ci/requirements-py36.yml
index 0d22fb26b79..d679c831cdc 100644
--- a/ci/requirements-py36.yml
+++ b/ci/requirements-py36.yml
@@ -10,6 +10,7 @@ dependencies:
- matplotlib
- netcdf4
- pytest
+ - flake8
- numpy
- pandas
- scipy
diff --git a/doc/whats-new.rst b/doc/whats-new.rst
index 241e5b7e49f..75aa94d1efc 100644
--- a/doc/whats-new.rst
+++ b/doc/whats-new.rst
@@ -217,6 +217,10 @@ Enhancements
(:issue:`576`).
By `Stephan Hoyer `_.
+- Added :py:func:`~xarray.show_versions` function to aid in debugging
+ (:issue:`1485`).
+ By `Joe Hamman` `_.
+
- Support using an existing, opened netCDF4 ``Dataset`` with
:py:class:`~xarray.backends.NetCDF4DataStore`. This permits creating an
:py:class:`~xarray.Dataset` from a netCDF4 ``Dataset`` that has been opened using
diff --git a/xarray/__init__.py b/xarray/__init__.py
index d2ce7d076f7..89c6ee7cd75 100644
--- a/xarray/__init__.py
+++ b/xarray/__init__.py
@@ -28,6 +28,7 @@
'the source directory, please instead create a new '
'virtual environment (using conda or virtualenv) and '
'then install it in-place by running: pip install -e .')
+from .util.print_versions import show_versions
from . import tutorial
from . import ufuncs
diff --git a/xarray/util/__init__.py b/xarray/util/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/xarray/util/print_versions.py b/xarray/util/print_versions.py
new file mode 100755
index 00000000000..095c7add84d
--- /dev/null
+++ b/xarray/util/print_versions.py
@@ -0,0 +1,151 @@
+'''utility functions for printing version information
+
+
+see pandas/pandas/util/_print_versions.py'''
+import os
+import platform
+import sys
+import struct
+import subprocess
+import codecs
+import locale
+import importlib
+
+
+def get_sys_info():
+ "Returns system information as a dict"
+
+ blob = []
+
+ # get full commit hash
+ commit = None
+ if os.path.isdir(".git") and os.path.isdir("xarray"):
+ try:
+ pipe = subprocess.Popen('git log --format="%H" -n 1'.split(" "),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ so, serr = pipe.communicate()
+ except:
+ pass
+ else:
+ if pipe.returncode == 0:
+ commit = so
+ try:
+ commit = so.decode('utf-8')
+ except ValueError:
+ pass
+ commit = commit.strip().strip('"')
+
+ blob.append(('commit', commit))
+
+ try:
+ (sysname, nodename, release,
+ version, machine, processor) = platform.uname()
+ blob.extend([
+ ("python", "%d.%d.%d.%s.%s" % sys.version_info[:]),
+ ("python-bits", struct.calcsize("P") * 8),
+ ("OS", "%s" % (sysname)),
+ ("OS-release", "%s" % (release)),
+ # ("Version", "%s" % (version)),
+ ("machine", "%s" % (machine)),
+ ("processor", "%s" % (processor)),
+ ("byteorder", "%s" % sys.byteorder),
+ ("LC_ALL", "%s" % os.environ.get('LC_ALL', "None")),
+ ("LANG", "%s" % os.environ.get('LANG', "None")),
+ ("LOCALE", "%s.%s" % locale.getlocale()),
+
+ ])
+ except:
+ pass
+
+ return blob
+
+
+def show_versions(as_json=False):
+ sys_info = get_sys_info()
+
+ deps = [
+ # (MODULE_NAME, f(mod) -> mod version)
+ ("xarray", lambda mod: mod.__version__),
+ ("pandas", lambda mod: mod.__version__),
+ ("numpy", lambda mod: mod.__version__),
+ ("scipy", lambda mod: mod.__version__),
+ # xarray optionals
+ ("netCDF4", lambda mod: mod.__version__),
+ # ("pydap", lambda mod: mod.version.version),
+ ("h5netcdf", lambda mod: mod.__version__),
+ ("Nio", lambda mod: mod.__version__),
+ ("bottleneck", lambda mod: mod.__version__),
+ ("cyordereddict", lambda mod: mod.__version__),
+ ("dask", lambda mod: mod.__version__),
+ ("matplotlib", lambda mod: mod.__version__),
+ ("cartopy", lambda mod: mod.__version__),
+ ("seaborn", lambda mod: mod.__version__),
+ # xarray setup/test
+ ("setuptools", lambda mod: mod.__version__),
+ ("pip", lambda mod: mod.__version__),
+ ("conda", lambda mod: mod.__version__),
+ ("pytest", lambda mod: mod.__version__),
+ # Misc.
+ ("IPython", lambda mod: mod.__version__),
+ ("sphinx", lambda mod: mod.__version__),
+ ]
+
+ deps_blob = list()
+ for (modname, ver_f) in deps:
+ try:
+ if modname in sys.modules:
+ mod = sys.modules[modname]
+ else:
+ mod = importlib.import_module(modname)
+ ver = ver_f(mod)
+ deps_blob.append((modname, ver))
+ except:
+ deps_blob.append((modname, None))
+
+ if (as_json):
+ try:
+ import json
+ except:
+ import simplejson as json
+
+ j = dict(system=dict(sys_info), dependencies=dict(deps_blob))
+
+ if as_json is True:
+ print(j)
+ else:
+ with codecs.open(as_json, "wb", encoding='utf8') as f:
+ json.dump(j, f, indent=2)
+
+ else:
+
+ print("\nINSTALLED VERSIONS")
+ print("------------------")
+
+ for k, stat in sys_info:
+ print("%s: %s" % (k, stat))
+
+ print("")
+ for k, stat in deps_blob:
+ print("%s: %s" % (k, stat))
+
+
+def main():
+ from optparse import OptionParser
+ parser = OptionParser()
+ parser.add_option("-j", "--json", metavar="FILE", nargs=1,
+ help="Save output as JSON into file, pass in "
+ "'-' to output to stdout")
+
+ (options, args) = parser.parse_args()
+
+ if options.json == "-":
+ options.json = True
+
+ show_versions(as_json=options.json)
+
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())