diff --git a/requirements-dev.txt b/requirements-dev.txt
index 5924a553..348c4bde 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -11,8 +11,9 @@ dash_auth==1.4.1
dash_core_components==1.15.0
dash_html_components==1.1.2
dash_renderer==1.9.0
+Werkzeug<=2.0.3
solvebio==2.12.0
pyyaml==5.3.1
click==7.1.2
ruamel.yaml==0.16.12
-pytest
\ No newline at end of file
+pytest
diff --git a/solvebio/global_search.py b/solvebio/global_search.py
index 22d77711..ed79b51e 100644
--- a/solvebio/global_search.py
+++ b/solvebio/global_search.py
@@ -23,6 +23,8 @@ def __init__(
query=None,
filters=None,
entities=None,
+ entities_match='any',
+ vault_scope='all',
ordering=None,
limit=float('inf'),
page_size=QueryBase.DEFAULT_PAGE_SIZE,
@@ -37,6 +39,8 @@ def __init__(
- `query` (optional): An optional query string (advanced search).
- `filters` (optional): Filter or List of filter objects.
- `entities` (optional): List of entity tuples to filter on (entity type, entity).
+ - `entities_match` (optional): Can be 'all' or 'any' (match any provided entity).
+ - `vault_scope` (optional): Can be 'all' or 'access'.
- `ordering` (optional): List of fields to order the results by.
- `limit` (optional): Maximum number of query results to return.
- `page_size` (optional): Number of results to fetch per query page.
@@ -49,12 +53,13 @@ def __init__(
self._data_url = '/v2/search'
self._query = query
self._entities = entities
+ self._entities_match = entities_match
+ self._vault_scope = vault_scope
self._ordering = ordering
self._result_class = result_class
self._debug = debug
self._raw_results = raw_results
self._error = None
- self._is_join = False
if filters:
if isinstance(filters, Filter):
@@ -97,6 +102,8 @@ def _clone(self, filters=None, entities=None, limit=None):
ordering=self._ordering,
page_size=self._page_size,
result_class=self._result_class,
+ vault_scope=self._vault_scope,
+ entities_match=self._entities_match,
debug=self._debug,
client=self._client)
new._filters += self._filters
@@ -124,9 +131,6 @@ def __len__(self):
SELECT * FROM
[WHERE condition] [LIMIT number]
)
"""
- if self._is_join:
- return len(self._buffer)
-
return super(GlobalSearch, self).__len__()
def _build_query(self, **kwargs):
@@ -148,6 +152,12 @@ def _build_query(self, **kwargs):
if self._ordering is not None:
q['ordering'] = self._ordering
+ if self._vault_scope is not None:
+ q['vault_scope'] = self._vault_scope
+
+ if self._entities_match is not None:
+ q['entities_match'] = self._entities_match
+
if self._debug:
q['debug'] = 'True'
@@ -158,14 +168,20 @@ def _build_query(self, **kwargs):
return q
def execute(self, offset=0, **query):
+ def _process_result(result):
+ # Internally the client uses object_type, not type
+ result['object_type'] = result['type']
+ if result['object_type'] == 'vault':
+ return Vault.construct_from(result)
+ else:
+ return Object.construct_from(result)
+
# Call superclass method execute
super(GlobalSearch, self).execute(offset, **query)
# Cast logical objects from response to Object/Vault instances
if not self._raw_results:
- self._response['results'] = [Vault.construct_from(result) if result['type'] == 'vault'
- else Object.construct_from(result)
- for result in self._response['results']]
+ self._response['results'] = [_process_result(i) for i in self._response['results']]
def entity(self, **kwargs):
"""
@@ -198,3 +214,12 @@ def subjects_count(self):
gs.execute()
return gs._response.get('subjects_count')
+
+ def vaults(self):
+ """Returns the list of vaults"""
+
+ # Executes a query to get a full API response which contains vaults list
+ gs = self.limit(0)
+ gs.execute(include_vaults=True)
+
+ return gs._response.get('vaults')
diff --git a/solvebio/resource/object.py b/solvebio/resource/object.py
index e48f30d2..7af07410 100644
--- a/solvebio/resource/object.py
+++ b/solvebio/resource/object.py
@@ -440,12 +440,9 @@ def __getattr__(self, name):
try:
return self[name]
except KeyError as err:
- # If the Object has a dataset_id, it is of object_type "dataset"
- # If there is no dataset_id, either this Object is a file or folder
- # or the resource has not yet been retrieved from the API.
- if name in valid_dataset_attrs and self.dataset_id:
+ if name in valid_dataset_attrs and self['object_type'] == "dataset":
return getattr(
- Dataset(self.dataset_id, client=self._client), name)
+ Dataset(self['id'], client=self._client), name)
raise AttributeError(*err.args)
@@ -458,7 +455,7 @@ def dataset(self):
"Only dataset objects have a Dataset resource. This is a {}"
.format(self.object_type))
- return Dataset.retrieve(self.dataset_id, client=self._client)
+ return Dataset.retrieve(self['id'], client=self._client)
@property
def parent(self):
@@ -560,7 +557,7 @@ def query(self, **params):
from solvebio.query import QueryFile
if self.is_dataset:
- return Dataset(self.dataset_id, client=self._client).query(**params)
+ return Dataset(self['id'], client=self._client).query(**params)
elif self.is_file:
return QueryFile(self['id'], client=self._client, **params)
else:
diff --git a/solvebio/test/test_dataset_migrations.py b/solvebio/test/test_dataset_migrations.py
index 0c39188c..397bf56a 100644
--- a/solvebio/test/test_dataset_migrations.py
+++ b/solvebio/test/test_dataset_migrations.py
@@ -117,10 +117,10 @@ def test_migration_target_dataset_object(self, Create):
"""Target is an Object of object_type=dataset"""
Create.side_effect = fake_migration_create
- source = self.client.Object(1, object_type='dataset')
- source.dataset_id = source.id
- target = self.client.Object(2, object_type='dataset')
- target.dataset_id = target.id
+ source = self.client.Object(1)
+ source['object_type'] = 'dataset'
+ target = self.client.Object(2)
+ target['object_type'] = 'dataset'
migration = source.migrate(target=target, follow=False)
self.assertEqual(migration.source_id, source.id)
self.assertEqual(migration.target_id, target.id)