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())