diff --git a/README.md b/README.md index 074bbca..3d4a5c8 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Python ScienceBase Utilities ============================ This Python module provides some basic services for interacting with ScienceBase. It requires the "requests" module to be installed, which can be found at -[http://docs.python-requests.org/en/latest/](http://docs.python-requests.org/en/latest/) +[http://docs.python-requests.org/en/latest/](http://docs.python-requests.org/en/latest/). If you get security errors also install requests[security] Quick Start @@ -80,6 +80,11 @@ List All Hidden Properties for a given Item: GET /catalog/item//hiddenP * `get_hidden_property(item_id, hiddenpropertyid)` Get a specific Hidden Property for a given Item : GET /catalog/item//hiddenProperties/ +* `get_item_ids_by_hidden_property(hidden_property)` +Get the ScienceBase IDs of Items associated with the given hidden property. Hidden property JSON +(for the hidden_property parameter) contains two fields, "type" and "value" both of which are +optional. + * `get_child_ids(parent_id)` Get the IDs of all immediate children of the ScienceBase item with the given ID (does not follow shortcuts). @@ -235,6 +240,17 @@ Find items containing the given text in the title of the item. Find items meeting the criteria in the specified search parameters. These are the same parameters that you pass to ScienceBase in an advanced search. +* `find_items_by_filter_and_hidden_property(params, hidden_property)` +Find items meeting the criteria in the specified search parameters and hidden property JSON. Hidden property JSON contains +two fields, "type" and "value" both of which are optional. **Warning**: Because of the way hidden property results must be +joined to ScienceBase Catalog search results, this method returns all matching items. Queries returning too many items may +be blocked by ScienceBase. + +* `find_hidden_property(hidden_property)` +Find ScienceBase Items by hidden property value. hidden_property: ScienceBase Item Hidden Property JSON: +`{"type": ..., "value": ...}`. Returns Item Hidden Property JSON containing the first page of matching +ScienceBase Items. Use the next() method for subsequent pages. + * `next(items)` Get the next page of results, where *items* is the current search results. diff --git a/sciencebasepy/SbSession.py b/sciencebasepy/SbSession.py index 9d21177..b27d218 100644 --- a/sciencebasepy/SbSession.py +++ b/sciencebasepy/SbSession.py @@ -181,6 +181,76 @@ def get_hidden_property(self, item_id, hidden_property_id): ret = self._session.get(self._base_item_url + item_id + '/hiddenProperties/' + hidden_property_id) return self._get_json(ret) + def find_hidden_property(self, hidden_property): + """Find ScienceBase Items by hidden property value + + :param hidden_property: ScienceBase Item Hidden Property JSON: {"type": ..., "value": ...} + :return: Item Hidden Property JSON containing the first page of matching ScienceBase Items. Use the next() method for + subsequent pages. + """ + ret = {} + if hidden_property: + params = {"max": 1000} + if "type" in hidden_property: + params["type"] = hidden_property["type"] + if "value" in hidden_property: + params["value"] = hidden_property["value"] + ret = self.get_json(self._base_sb_url + "itemHiddenProperties", params = params) + return ret + + def find_items_by_filter_and_hidden_property(self, params, hidden_property): + """Search for ScienceBase items by filter and hidden property + + Warning: Because of the way hidden property results must be joined to ScienceBase Catalog search results, + this method returns all matching items. Queries returning too many items may be blocked by ScienceBase. + + :param params: ScienceBase Catalog search parameters + :param hidden_property: ScienceBase Item Hidden Property JSON: {"type": ..., "value": ...} + :return: ScienceBase Catalog search response object containing the first page of results for the search + """ + # + # Retrieve all of the hidden property results + # + ret = [] + properties = [] + + response = self.find_hidden_property(hidden_property) + while response and "itemHiddenProperties" in response: + for item_hidden_property in response["itemHiddenProperties"]: + properties.append(item_hidden_property) + response = self.next(response) + # + # Save a list of all the ScienceBase Item IDs found, and map properties to their item + # + ids = [] + item_props = {} + for prop in properties: + ids.append(prop["itemId"]) + item_props[prop["itemId"]] = {prop["type"]: prop["value"]} + # + # Now perform the ScienceBase Item search part of the query, saving only Items whose + # ID is in the list of matching hidden property items + # + response = self.find_items(params) + while response and "items" in response and response["items"]: + for item in response["items"]: + if item["id"] in ids: + item["hiddenProperties"] = item_props[item["id"]] + ret.append(item) + response = self.next(response) + return ret + + def get_item_ids_by_hidden_property(self, hidden_property): + """Get the ScienceBase IDs of Items associated with the given hidden property + + :param hidden_property: ScienceBase Item Hidden Property JSON: {"type": ..., "value": ...} + :return: List of ScienceBase Item IDs containing the given hidden property + """ + ret = [] + for item_hidden_property in self.find_hidden_property(hidden_property): + ret.append(item_hidden_property["itemId"]) + return ret + def create_item(self, item_json): """Create a new Item in ScienceBase @@ -694,7 +764,7 @@ def find_items(self, params): :param params: ScienceBase Catalog search parameters :return: ScienceBase Catalog search response object containing the next page of results for the search """ - return self._get_json(self._session.get(self._base_items_url, params=params)) + return self.get_json(self._base_items_url, params=params) def next(self, items): """Get the next set of items from the search @@ -703,8 +773,12 @@ def next(self, items): :return: ScienceBase Catalog search response object containing the next page of results for the search """ ret_val = None + # Items response if 'nextlink' in items: - ret_val = self._get_json(self._session.get(items['nextlink']['url'])) + ret_val = self.get_json(items['nextlink']['url']) + # Hidden properties response + elif 'links' in items and 'next' in items['links']: + ret_val = self.get_json(items['links']['next']) return ret_val def previous(self, items): @@ -714,8 +788,12 @@ def previous(self, items): :return: ScienceBase Catalog search response object containing the previous page of results for the search """ ret_val = None + # Items response if 'prevlink' in items: - ret_val = self._get_json(self._session.get(items['prevlink']['url'])) + ret_val = self.get_json(items['prevlink']['url']) + # Hidden properties response + elif 'links' in items and 'prev' in items['links']: + ret_val = self.get_json(items['links']['prev']) return ret_val def find_items_by_any_text(self, text): @@ -742,13 +820,18 @@ def get(self, url): """ return self._get_text(self._session.get(url)) - def get_json(self, url): + def get_json(self, url, params = None): """Get the JSON response of the given URL :param url: URL to request via HTTP GET :return: JSON response """ - return self._get_json(self._session.get(url)) + ret = None + if params: + ret = self._get_json(self._session.get(url, params=params)) + else: + ret = self._get_json(self._session.get(url)) + return ret def get_directory_contact(self, party_id): """Get the Directory Contact JSON for the contact with the given party ID @@ -879,7 +962,7 @@ def get_permissions(self, item_id): :param item_id: The ID of the ScienceBase item :return: The permissions JSON for the given item """ - return self._get_json(self._session.get(self._base_item_url + item_id + "/permissions/")) + return self.get_json(self._base_item_url + item_id + "/permissions/") def set_permissions(self, item_id, acls): """Set permissions for the item identified by item_id. WARNING: Advanced use only. ACL JSON diff --git a/setup.py b/setup.py index 49fc64c..7df0018 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ long_description = fh.read() setuptools.setup(name='sciencebasepy', - version='1.6.3', + version='1.6.4', author="USGS ScienceBase Development Team", author_email="sciencebase@usgs.gov", description="Python ScienceBase Utilities", @@ -20,5 +20,8 @@ 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6' ], )