Skip to content

Commit

Permalink
Support opening password protected datasets over Opendap (Fixes #1068) (
Browse files Browse the repository at this point in the history
#1570)

* Use the PydapDataStore.open() classmethod

* Added test for pydap password support

* Added pydap password change to whats-new.rst

* Changed test_password to test_session

* Documented type of ds in PydapDataStore

* Fixed documentation

* Removed unused import

* Added docs for using sessions with pydap

* Fixed typo

* Fixed formatting after merge
  • Loading branch information
mrpgraae authored and shoyer committed Sep 15, 2017
1 parent ae4df1d commit 3fb5cbb
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 3 deletions.
32 changes: 32 additions & 0 deletions doc/io.rst
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,38 @@ over the network until we look at particular values:

.. image:: _static/opendap-prism-tmax.png

Some servers require authentication before we can access the data. For this
purpose we can explicitly create a :py:class:`~xarray.backends.PydapDataStore`
and pass in a `Requests`__ session object. For example for
HTTP Basic authentication::

import xarray as xr
import requests

session = requests.Session()
session.auth = ('username', 'password')

store = xr.backends.PydapDataStore.open('http://example.com/data',
session=session)
ds = xr.open_dataset(store)

`Pydap's cas module`__ has functions that generate custom sessions for
servers that use CAS single sign-on. For example, to connect to servers
that require NASA's URS authentication::

import xarray as xr
from pydata.cas.urs import setup_session

ds_url = 'https://gpm1.gesdisc.eosdis.nasa.gov/opendap/hyrax/example.nc'

session = setup_session('username', 'password', check_url=ds_url)
store = xr.backends.PydapDataStore.open(ds_url, session=session)

ds = xr.open_dataset(store)

__ http://docs.python-requests.org
__ http://pydap.readthedocs.io/en/latest/client.html#authentication

.. _io.rasterio:

Rasterio
Expand Down
7 changes: 7 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ Enhancements
By `Joe Hamman <https://github.com/jhamman>`_ and
`Gerrit Holl <https://github.com/gerritholl>`_.

- Changed :py:class:`~xarray.backends.PydapDataStore` to take a Pydap dataset.
This permits opening Opendap datasets that require authentication, by
instantiating a Pydap dataset with a session object. Also added
:py:meth:`xarray.backends.PydapDataStore.open` which takes a url and session
object (:issue:`1068`).
By `Philip Graae <https://github.com/mrpgraae>`_.

- Support applying rolling window operations using bottleneck's moving window
functions on data stored as dask arrays (:issue:`1279`).
By `Joe Hamman <https://github.com/jhamman>`_.
Expand Down
2 changes: 1 addition & 1 deletion xarray/backends/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ def maybe_decode_store(store, lock=False):
store = backends.ScipyDataStore(filename_or_obj,
autoclose=autoclose)
elif engine == 'pydap':
store = backends.PydapDataStore(filename_or_obj)
store = backends.PydapDataStore.open(filename_or_obj)
elif engine == 'h5netcdf':
store = backends.H5NetCDFStore(filename_or_obj, group=group,
autoclose=autoclose)
Expand Down
14 changes: 12 additions & 2 deletions xarray/backends/pydap_.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,19 @@ class PydapDataStore(AbstractDataStore):
This store provides an alternative way to access OpenDAP datasets that may
be useful if the netCDF4 library is not available.
"""
def __init__(self, url):
def __init__(self, ds):
"""
Parameters
----------
ds : pydap DatasetType
"""
self.ds = ds

@classmethod
def open(cls, url, session=None):
import pydap.client
self.ds = pydap.client.open_url(url)
ds = pydap.client.open_url(url, session=session)
return cls(ds)

def open_store_variable(self, var):
data = indexing.LazilyIndexedArray(PydapArrayWrapper(var))
Expand Down
10 changes: 10 additions & 0 deletions xarray/tests/test_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
assert_identical)
from .test_dataset import create_test_data

from xarray.tests import mock

try:
import netCDF4 as nc4
except ImportError:
Expand Down Expand Up @@ -1509,6 +1511,14 @@ def test_cmp_local_file(self):
self.assertDatasetEqual(actual.isel(j=slice(1, 2)),
expected.isel(j=slice(1, 2)))

def test_session(self):
from pydap.cas.urs import setup_session

session = setup_session('XarrayTestUser', 'Xarray2017')
with mock.patch('pydap.client.open_url') as mock_func:
xr.backends.PydapDataStore.open('http://test.url', session=session)
mock_func.assert_called_with('http://test.url', session=session)

@requires_dask
def test_dask(self):
with self.create_datasets(chunks={'j': 2}) as (actual, expected):
Expand Down

0 comments on commit 3fb5cbb

Please sign in to comment.