A HydroShare object for querying HydroShare's REST API. Provide a username and password at initialization or call the sign_in() method to prompt for the username and password.

If using OAuth2 is desired, provide the client_id and token to use. If on CUAHSI JupyterHub or another JupyterHub environment that authenticates with Hydroshare, call the hs_juptyerhub() method to read the credentials from Jupyterhub.

:param username: A HydroShare username :param password: A HydroShare password associated with the username :param host: The host to use, defaults to www.hydroshare.org :param protocol: The protocol to use, defaults to https :param port: The port to use, defaults to 443 :param client_id: The client id associated with the OAuth2 token :param token: The OAuth2 token to use

Source code in hsclient\hydroshare.py
class HydroShare:
    """
    A HydroShare object for querying HydroShare's REST API.  Provide a username and password at initialization or call
    the sign_in() method to prompt for the username and password.

    If using OAuth2 is desired, provide the client_id and token to use.  If on CUAHSI JupyterHub or another JupyterHub
    environment that authenticates with Hydroshare, call the hs_juptyerhub() method to read the credentials from
    Jupyterhub.

    :param username: A HydroShare username
    :param password: A HydroShare password associated with the username
    :param host: The host to use, defaults to `www.hydroshare.org`
    :param protocol: The protocol to use, defaults to `https`
    :param port: The port to use, defaults to `443`
    :param client_id: The client id associated with the OAuth2 token
    :param token: The OAuth2 token to use
    """

    default_host = 'www.hydroshare.org'
    default_protocol = "https"
    default_port = 443

    def __init__(
        self,
        username: str = None,
        password: str = None,
        host: str = default_host,
        protocol: str = default_protocol,
        port: int = default_port,
        client_id: str = None,
        token: Union[Token, Dict[str, str]] = None,
    ):
        if client_id or token:
            if not client_id or not token:
                raise ValueError("Oauth2 requires a client_id to be paired with a token")
            else:
                self._hs_session = HydroShareSession(
                    host=host, protocol=protocol, port=port, client_id=client_id, token=token
                )
                self.my_user_info()  # validate credentials
        else:
            self._hs_session = HydroShareSession(
                username=username, password=password, host=host, protocol=protocol, port=port
            )
            if username or password:
                self.my_user_info()  # validate credentials

        self._resource_object_cache: Dict[str, Resource] = dict()

    def sign_in(self) -> None:
        """Prompts for username/password.  Useful for avoiding saving your HydroShare credentials to a notebook"""
        username = input("Username: ").strip()
        password = getpass.getpass("Password for {}: ".format(username))
        self._hs_session.set_auth((username, password))
        self.my_user_info()  # validate credentials

    @classmethod
    def hs_juptyerhub(cls, hs_auth_path="/home/jovyan/data/.hs_auth"):
        """
        Create a new HydroShare object using OAuth2 credentials stored in a canonical CUAHSI
        Jupyterhub OAuth2 pickle file (stored at :param hs_auth_path:).

        Provide a non-default (default: `/home/jovyan/data/.hs_auth`) path to the hs_auth file with
        :param hs_auth_path:.
        """
        if not os.path.isfile(hs_auth_path):
            raise ValueError(f"hs_auth_path {hs_auth_path} does not exist.")
        with open(hs_auth_path, 'rb') as f:
            token, client_id = pickle.load(f)
        instance = cls(client_id=client_id, token=token)
        instance.my_user_info()  # validate credentials
        return instance

    def search(
        self,
        creator: str = None,
        contributor: str = None,
        owner: str = None,
        group_name: str = None,
        from_date: datetime = None,
        to_date: datetime = None,
        edit_permission: bool = False,
        resource_types: List[str] = [],
        subject: List[str] = [],
        full_text_search: str = None,
        published: bool = False,
        spatial_coverage: Union[BoxCoverage, PointCoverage] = None,
    ):
        """
        Query the GET /hsapi/resource/ REST end point of the HydroShare server.
        :param creator: Filter results by the HydroShare username or email
        :param author: Filter results by the HydroShare username or email
        :param owner: Filter results by the HydroShare username or email
        :param group_name: Filter results by the HydroShare group name associated with resources
        :param from_date: Filter results to those created after from_date.  Must be datetime.date.
        :param to_date: Filter results to those created before to_date.  Must be datetime.date.  Because dates have
            no time information, you must specify date+1 day to get results for date (e.g. use 2015-05-06 to get
            resources created up to and including 2015-05-05)
        :param types: Filter results to particular HydroShare resource types (Deprecated, all types are Composite)
        :param subject: Filter by comma separated list of subjects
        :param full_text_search: Filter by full text search
        :param edit_permission: Filter by boolean edit permission
        :param published: Filter by boolean published status
        :param spatial_coverage: Filtering by spatial coverage raises a 500, do not use

        :return: A generator to iterate over a ResourcePreview object
        """

        params = {"edit_permission": edit_permission, "published": published}
        if creator:
            params["creator"] = creator
        if contributor:
            params["author"] = contributor
        if owner:
            params["owner"] = owner
        if group_name:
            params["group"] = group_name
        if resource_types:
            params["type[]"] = resource_types
        if subject:
            params["subject"] = ",".join(subject)
        if full_text_search:
            params["full_text_search"] = full_text_search
        if from_date:
            params["from_date"] = from_date.strftime('%Y-%m-%d')
        if to_date:
            params["to_date"] = to_date.strftime('%Y-%m-%d')
        if spatial_coverage:
            yield Exception(
                "Bad Request, status_code 400, spatial_coverage queries are disabled."
            )
            # TODO: re-enable after resolution of https://github.com/hydroshare/hydroshare/issues/5240
            # params["coverage_type"] = spatial_coverage.type
            # if spatial_coverage.type == "point":
            #     params["north"] = spatial_coverage.north
            #     params["east"] = spatial_coverage.east
            # else:
            #     params["north"] = spatial_coverage.northlimit
            #     params["east"] = spatial_coverage.eastlimit
            #     params["south"] = spatial_coverage.southlimit
            #     params["west"] = spatial_coverage.westlimit
        response = self._hs_session.get("/hsapi/resource/", 200, params=params)

        res = response.json()
        results = res['results']
        for item in results:
            yield ResourcePreview(**item)

        while res['next']:
            next_url = res['next']
            next_url = urlparse(next_url)
            path = next_url.path
            params = next_url.query
            response = self._hs_session.get(path, 200, params=params)
            res = response.json()
            results = res['results']
            for item in results:
                yield ResourcePreview(**item)

    def resource(self, resource_id: str, validate: bool = True, use_cache: bool = True) -> Resource:
        """
        Creates a resource object from HydroShare with the provided resource_id
        :param resource_id: The resource id of the resource to retrieve
        :param validate: Defaults to True, set to False to not validate the resource exists
        :param use_cache: Defaults to True, set to False to skip the cache, and always retrieve the
            resource from HydroShare. This parameter also does not cache the retrieved Resource
            object.
        :return: A Resource object representing a resource on HydroShare
        """
        if resource_id in self._resource_object_cache and use_cache:
            return self._resource_object_cache[resource_id]

        res = Resource("/resource/{}/data/resourcemap.xml".format(resource_id), self._hs_session)
        if validate:
            res.metadata

        if use_cache:
            self._resource_object_cache[resource_id] = res
        return res

    def create(self, use_cache: bool = True) -> Resource:
        """
        Creates a new resource on HydroShare
        :param use_cache: Defaults to True, set to False to skip the cache, and always retrieve the
            resource from HydroShare. This parameter also does not cache the retrieved Resource
            object.
        :return: A Resource object representing a resource on HydroShare
        """
        response = self._hs_session.post('/hsapi/resource/', status_code=201)
        resource_id = response.json()['resource_id']
        return self.resource(resource_id, use_cache=use_cache)

    def user(self, user_id: int) -> User:
        """
        Retrieves the user details of a Hydroshare user
        :param user_id: The user id of the user details to retrieve
        :return: User object representing the user details
        """
        response = self._hs_session.get(f'/hsapi/userDetails/{user_id}/', status_code=200)
        return User(**response.json())

    def my_user_info(self):
        """
        Retrieves the user info of the user's credentials provided
        :return: JSON object representing the user info
        """
        response = self._hs_session.get('/hsapi/userInfo/', status_code=200)
        return response.json()

create(use_cache=True)

Creates a new resource on HydroShare :param use_cache: Defaults to True, set to False to skip the cache, and always retrieve the resource from HydroShare. This parameter also does not cache the retrieved Resource object. :return: A Resource object representing a resource on HydroShare

Source code in hsclient\hydroshare.py
def create(self, use_cache: bool = True) -> Resource:
    """
    Creates a new resource on HydroShare
    :param use_cache: Defaults to True, set to False to skip the cache, and always retrieve the
        resource from HydroShare. This parameter also does not cache the retrieved Resource
        object.
    :return: A Resource object representing a resource on HydroShare
    """
    response = self._hs_session.post('/hsapi/resource/', status_code=201)
    resource_id = response.json()['resource_id']
    return self.resource(resource_id, use_cache=use_cache)

hs_juptyerhub(hs_auth_path='/home/jovyan/data/.hs_auth') classmethod

Create a new HydroShare object using OAuth2 credentials stored in a canonical CUAHSI Jupyterhub OAuth2 pickle file (stored at :param hs_auth_path:).

Provide a non-default (default: /home/jovyan/data/.hs_auth) path to the hs_auth file with :param hs_auth_path:.

Source code in hsclient\hydroshare.py
@classmethod
def hs_juptyerhub(cls, hs_auth_path="/home/jovyan/data/.hs_auth"):
    """
    Create a new HydroShare object using OAuth2 credentials stored in a canonical CUAHSI
    Jupyterhub OAuth2 pickle file (stored at :param hs_auth_path:).

    Provide a non-default (default: `/home/jovyan/data/.hs_auth`) path to the hs_auth file with
    :param hs_auth_path:.
    """
    if not os.path.isfile(hs_auth_path):
        raise ValueError(f"hs_auth_path {hs_auth_path} does not exist.")
    with open(hs_auth_path, 'rb') as f:
        token, client_id = pickle.load(f)
    instance = cls(client_id=client_id, token=token)
    instance.my_user_info()  # validate credentials
    return instance

my_user_info()

Retrieves the user info of the user's credentials provided :return: JSON object representing the user info

Source code in hsclient\hydroshare.py
def my_user_info(self):
    """
    Retrieves the user info of the user's credentials provided
    :return: JSON object representing the user info
    """
    response = self._hs_session.get('/hsapi/userInfo/', status_code=200)
    return response.json()

resource(resource_id, validate=True, use_cache=True)

Creates a resource object from HydroShare with the provided resource_id :param resource_id: The resource id of the resource to retrieve :param validate: Defaults to True, set to False to not validate the resource exists :param use_cache: Defaults to True, set to False to skip the cache, and always retrieve the resource from HydroShare. This parameter also does not cache the retrieved Resource object. :return: A Resource object representing a resource on HydroShare

Source code in hsclient\hydroshare.py
def resource(self, resource_id: str, validate: bool = True, use_cache: bool = True) -> Resource:
    """
    Creates a resource object from HydroShare with the provided resource_id
    :param resource_id: The resource id of the resource to retrieve
    :param validate: Defaults to True, set to False to not validate the resource exists
    :param use_cache: Defaults to True, set to False to skip the cache, and always retrieve the
        resource from HydroShare. This parameter also does not cache the retrieved Resource
        object.
    :return: A Resource object representing a resource on HydroShare
    """
    if resource_id in self._resource_object_cache and use_cache:
        return self._resource_object_cache[resource_id]

    res = Resource("/resource/{}/data/resourcemap.xml".format(resource_id), self._hs_session)
    if validate:
        res.metadata

    if use_cache:
        self._resource_object_cache[resource_id] = res
    return res

search(creator=None, contributor=None, owner=None, group_name=None, from_date=None, to_date=None, edit_permission=False, resource_types=[], subject=[], full_text_search=None, published=False, spatial_coverage=None)

Query the GET /hsapi/resource/ REST end point of the HydroShare server. :param creator: Filter results by the HydroShare username or email :param author: Filter results by the HydroShare username or email :param owner: Filter results by the HydroShare username or email :param group_name: Filter results by the HydroShare group name associated with resources :param from_date: Filter results to those created after from_date. Must be datetime.date. :param to_date: Filter results to those created before to_date. Must be datetime.date. Because dates have no time information, you must specify date+1 day to get results for date (e.g. use 2015-05-06 to get resources created up to and including 2015-05-05) :param types: Filter results to particular HydroShare resource types (Deprecated, all types are Composite) :param subject: Filter by comma separated list of subjects :param full_text_search: Filter by full text search :param edit_permission: Filter by boolean edit permission :param published: Filter by boolean published status :param spatial_coverage: Filtering by spatial coverage raises a 500, do not use

:return: A generator to iterate over a ResourcePreview object

Source code in hsclient\hydroshare.py
def search(
    self,
    creator: str = None,
    contributor: str = None,
    owner: str = None,
    group_name: str = None,
    from_date: datetime = None,
    to_date: datetime = None,
    edit_permission: bool = False,
    resource_types: List[str] = [],
    subject: List[str] = [],
    full_text_search: str = None,
    published: bool = False,
    spatial_coverage: Union[BoxCoverage, PointCoverage] = None,
):
    """
    Query the GET /hsapi/resource/ REST end point of the HydroShare server.
    :param creator: Filter results by the HydroShare username or email
    :param author: Filter results by the HydroShare username or email
    :param owner: Filter results by the HydroShare username or email
    :param group_name: Filter results by the HydroShare group name associated with resources
    :param from_date: Filter results to those created after from_date.  Must be datetime.date.
    :param to_date: Filter results to those created before to_date.  Must be datetime.date.  Because dates have
        no time information, you must specify date+1 day to get results for date (e.g. use 2015-05-06 to get
        resources created up to and including 2015-05-05)
    :param types: Filter results to particular HydroShare resource types (Deprecated, all types are Composite)
    :param subject: Filter by comma separated list of subjects
    :param full_text_search: Filter by full text search
    :param edit_permission: Filter by boolean edit permission
    :param published: Filter by boolean published status
    :param spatial_coverage: Filtering by spatial coverage raises a 500, do not use

    :return: A generator to iterate over a ResourcePreview object
    """

    params = {"edit_permission": edit_permission, "published": published}
    if creator:
        params["creator"] = creator
    if contributor:
        params["author"] = contributor
    if owner:
        params["owner"] = owner
    if group_name:
        params["group"] = group_name
    if resource_types:
        params["type[]"] = resource_types
    if subject:
        params["subject"] = ",".join(subject)
    if full_text_search:
        params["full_text_search"] = full_text_search
    if from_date:
        params["from_date"] = from_date.strftime('%Y-%m-%d')
    if to_date:
        params["to_date"] = to_date.strftime('%Y-%m-%d')
    if spatial_coverage:
        yield Exception(
            "Bad Request, status_code 400, spatial_coverage queries are disabled."
        )
        # TODO: re-enable after resolution of https://github.com/hydroshare/hydroshare/issues/5240
        # params["coverage_type"] = spatial_coverage.type
        # if spatial_coverage.type == "point":
        #     params["north"] = spatial_coverage.north
        #     params["east"] = spatial_coverage.east
        # else:
        #     params["north"] = spatial_coverage.northlimit
        #     params["east"] = spatial_coverage.eastlimit
        #     params["south"] = spatial_coverage.southlimit
        #     params["west"] = spatial_coverage.westlimit
    response = self._hs_session.get("/hsapi/resource/", 200, params=params)

    res = response.json()
    results = res['results']
    for item in results:
        yield ResourcePreview(**item)

    while res['next']:
        next_url = res['next']
        next_url = urlparse(next_url)
        path = next_url.path
        params = next_url.query
        response = self._hs_session.get(path, 200, params=params)
        res = response.json()
        results = res['results']
        for item in results:
            yield ResourcePreview(**item)

sign_in()

Prompts for username/password. Useful for avoiding saving your HydroShare credentials to a notebook

Source code in hsclient\hydroshare.py
def sign_in(self) -> None:
    """Prompts for username/password.  Useful for avoiding saving your HydroShare credentials to a notebook"""
    username = input("Username: ").strip()
    password = getpass.getpass("Password for {}: ".format(username))
    self._hs_session.set_auth((username, password))
    self.my_user_info()  # validate credentials

user(user_id)

Retrieves the user details of a Hydroshare user :param user_id: The user id of the user details to retrieve :return: User object representing the user details

Source code in hsclient\hydroshare.py
def user(self, user_id: int) -> User:
    """
    Retrieves the user details of a Hydroshare user
    :param user_id: The user id of the user details to retrieve
    :return: User object representing the user details
    """
    response = self._hs_session.get(f'/hsapi/userDetails/{user_id}/', status_code=200)
    return User(**response.json())